fix small youtube embed - allow to override max_width/max_height in EmbedBlock

pull/7288/head
Petr Dlouhý 2021-02-26 16:56:07 +01:00 zatwierdzone przez Matt Westcott
rodzic a64eb1f2f3
commit 50e4f5151d
10 zmienionych plików z 39 dodań i 22 usunięć

Wyświetl plik

@ -10,6 +10,7 @@ Changelog
* Added `full_url` property to image renditions (Shreyash Srivastava)
* Added locale selector when choosing translatable snippets (Karl Hobley)
* Added `WAGTAIL_WORKFLOW_ENABLED` setting for enabling / disabling moderation workflows globally (Matt Westcott)
* Allow specifying `max_width` and `max_height` on EmbedBlock (Petr Dlouhý)
* Fix: Invalid filter values for foreign key fields in the API now give an error instead of crashing (Tidjani Dia)
* Fix: Ordering specified in `construct_explorer_page_queryset` hook is now taken into account again by the page explorer API (Andre Fonseca)
* Fix: Deleting a page from its listing view no longer results in a 404 error (Tidjani Dia)

Wyświetl plik

@ -33,6 +33,8 @@ nest the embed code.
The :class:`~wagtail.embeds.block.EmbedBlock` block type allows embeds
to be placed into a ``StreamField``.
The ``max_width`` and ``max_height`` arguments are sent to the provider when fetching the embed code.
For example:
.. code-block:: python
@ -42,7 +44,7 @@ For example:
class MyStreamField(blocks.StreamBlock):
...
embed = EmbedBlock()
embed = EmbedBlock(max_width=800, max_height=400)
``{% embed %}`` tag
-------------------

Wyświetl plik

@ -332,6 +332,8 @@ Field block types
A field for the editor to enter a URL to a media item (such as a YouTube video) to appear as embedded media on the page. The following keyword arguments are accepted in addition to the standard ones:
:param required: If true (the default), the field cannot be left blank.
:param max_width: The maximum width of the embed, in pixels; this will be passed to the provider when requesting the embed.
:param max_height: The maximum height of the embed, in pixels; this will be passed to the provider when requesting the embed.
:param max_length: The maximum allowed length of the field.
:param min_length: The minimum allowed length of the field.
:param help_text: Help text to display alongside the field.

Wyświetl plik

@ -18,6 +18,7 @@ Other features
* Added ``full_url`` property to image renditions (Shreyash Srivastava)
* Added locale selector when choosing translatable snippets (Karl Hobley)
* Added ``WAGTAIL_WORKFLOW_ENABLED`` setting for enabling / disabling moderation workflows globally (Matt Westcott)
* Allow specifying ``max_width`` and ``max_height`` on EmbedBlock (Petr Dlouhý)
Bug fixes
~~~~~~~~~

Wyświetl plik

@ -14,12 +14,14 @@ class EmbedValue:
we want to be able to do {% embed value.url 500 %} without
doing a redundant fetch of the embed at the default width.
"""
def __init__(self, url):
def __init__(self, url, max_width=None, max_height=None):
self.url = url
self.max_width = max_width
self.max_height = max_height
@cached_property
def html(self):
return embed_to_frontend_html(self.url)
return embed_to_frontend_html(self.url, self.max_width, self.max_height)
def __str__(self):
return self.html
@ -34,7 +36,7 @@ class EmbedBlock(blocks.URLBlock):
return self.meta.default
else:
# assume default has been passed as a string
return EmbedValue(self.meta.default)
return EmbedValue(self.meta.default, getattr(self.meta, 'max_width', None), getattr(self.meta, 'max_height', None))
def to_python(self, value):
# The JSON representation of an EmbedBlock's value is a URL string;
@ -42,7 +44,7 @@ class EmbedBlock(blocks.URLBlock):
if not value:
return None
else:
return EmbedValue(value)
return EmbedValue(value, getattr(self.meta, 'max_width', None), getattr(self.meta, 'max_height', None))
def get_prep_value(self, value):
# serialisable value should be a URL string
@ -63,7 +65,7 @@ class EmbedBlock(blocks.URLBlock):
if not value:
return None
else:
return EmbedValue(value)
return EmbedValue(value, getattr(self.meta, 'max_width', None), getattr(self.meta, 'max_height', None))
def clean(self, value):
if isinstance(value, EmbedValue) and not value.html:

Wyświetl plik

@ -3,13 +3,14 @@ from hashlib import md5
from django.utils.timezone import now
from ..core.utils import accepts_kwarg
from .exceptions import EmbedUnsupportedProviderException
from .finders import get_finders
from .models import Embed
def get_embed(url, max_width=None, finder=None):
embed_hash = get_embed_hash(url, max_width)
def get_embed(url, max_width=None, max_height=None, finder=None):
embed_hash = get_embed_hash(url, max_width, max_height)
# Check database
try:
@ -20,14 +21,17 @@ def get_embed(url, max_width=None, finder=None):
# Get/Call finder
if not finder:
def finder(url, max_width=None):
def finder(url, max_width=None, max_height=None):
for finder in get_finders():
if finder.accept(url):
return finder.find_embed(url, max_width=max_width)
kwargs = {}
if accepts_kwarg(finder.find_embed, 'max_height'):
kwargs['max_height'] = max_height
return finder.find_embed(url, max_width=max_width, **kwargs)
raise EmbedUnsupportedProviderException
embed_dict = finder(url, max_width)
embed_dict = finder(url, max_width, max_height)
# Make sure width and height are valid integers before inserting into database
try:
@ -65,10 +69,13 @@ def get_embed(url, max_width=None, finder=None):
return embed
def get_embed_hash(url, max_width=None):
def get_embed_hash(url, max_width=None, max_height=None):
h = md5()
h.update(url.encode("utf-8"))
if max_width is not None:
h.update(b"\n")
h.update(str(max_width).encode("utf-8"))
if max_height is not None:
h.update(b"\n")
h.update(str(max_height).encode("utf-8"))
return h.hexdigest()

Wyświetl plik

@ -45,7 +45,7 @@ class OEmbedFinder(EmbedFinder):
def accept(self, url):
return self._get_endpoint(url) is not None
def find_embed(self, url, max_width=None):
def find_embed(self, url, max_width=None, max_height=None):
# Find provider
endpoint = self._get_endpoint(url)
if endpoint is None:
@ -57,6 +57,8 @@ class OEmbedFinder(EmbedFinder):
params['format'] = 'json'
if max_width:
params['maxwidth'] = max_width
if max_height:
params['maxheight'] = max_height
# Perform request
request = Request(endpoint + '?' + urlencode(params))

Wyświetl plik

@ -4,9 +4,9 @@ from wagtail.embeds import embeds
from wagtail.embeds.exceptions import EmbedException
def embed_to_frontend_html(url):
def embed_to_frontend_html(url, max_width=None, max_height=None):
try:
embed = embeds.get_embed(url)
embed = embeds.get_embed(url, max_width, max_height)
# Render template
return render_to_string('wagtailembeds/embed_frontend.html', {

Wyświetl plik

@ -122,7 +122,7 @@ class TestEmbeds(TestCase):
def setUp(self):
self.hit_count = 0
def dummy_finder(self, url, max_width=None):
def dummy_finder(self, url, max_width=None, max_height=None):
# Up hit count
self.hit_count += 1
@ -175,7 +175,7 @@ class TestEmbeds(TestCase):
self.assertFalse(embed.is_responsive)
self.assertIsNone(embed.cache_until)
def dummy_cache_until_finder(self, url, max_width=None):
def dummy_cache_until_finder(self, url, max_width=None, max_height=None):
# Up hit count
self.hit_count += 1
@ -210,7 +210,7 @@ class TestEmbeds(TestCase):
self.assertEqual(embed, embed_3)
self.assertEqual(embed_3.cache_until, future_dt)
def dummy_finder_invalid_width(self, url, max_width=None):
def dummy_finder_invalid_width(self, url, max_width=None, max_height=None):
# Return a record with an invalid width
return {
'title': "Test: " + url,
@ -228,7 +228,7 @@ class TestEmbeds(TestCase):
self.assertEqual(embed.width, None)
def test_no_html(self):
def no_html_finder(url, max_width=None):
def no_html_finder(url, max_width=None, max_height=None):
"""
A finder which returns everything but HTML
"""
@ -710,7 +710,7 @@ class TestEmbedBlock(TestCase):
self.assertIn('<h1>Hello world!</h1>', result)
# Check that get_embed was called correctly
get_embed.assert_any_call('http://www.example.com/foo')
get_embed.assert_any_call('http://www.example.com/foo', None, None)
@patch('wagtail.embeds.embeds.get_embed')
def test_render_within_structblock(self, get_embed):
@ -735,7 +735,7 @@ class TestEmbedBlock(TestCase):
self.assertIn('<h1>Hello world!</h1>', result)
# Check that get_embed was called correctly
get_embed.assert_any_call('http://www.example.com/foo')
get_embed.assert_any_call('http://www.example.com/foo', None, None)
def test_value_from_form(self):
"""

Wyświetl plik

@ -129,4 +129,4 @@ class TestFrontendMediaEmbedHandler(TestCase):
result = expand_db_html('<p>1 2 <embed embedtype="media" url="https://www.youtube.com/watch?v=O7D-1RG-VRk&amp;t=25" /> 3 4</p>')
self.assertIn('test html', result)
get_embed.assert_called_with('https://www.youtube.com/watch?v=O7D-1RG-VRk&t=25')
get_embed.assert_called_with('https://www.youtube.com/watch?v=O7D-1RG-VRk&t=25', None, None)