123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- .. _embedded_content:
- ================
- Embedded content
- ================
- Wagtail supports generating embed code from URLs to content on external
- providers such as Youtube or Twitter. By default, Wagtail will fetch the embed
- code directly from the relevant provider's site using the oEmbed protocol.
- Wagtail has a built-in list of the most common providers and this list can be
- changed :ref:`with a setting <customising_embed_providers>`. Wagtail also supports
- fetching embed code using `Embedly`_ and :ref:`custom embed finders <custom_embed_finders>`.
- Embedding content on your site
- ==============================
- Wagtail's embeds module should work straight out of the box for most providers.
- You can use any of the following methods to call the module:
- Rich text
- ---------
- Wagtail's default rich text editor has a "media" icon that allows embeds to be
- placed into rich text. You don't have to do anything to enable this; just make
- sure the rich text field's content is being passed through the ``|richtext``
- filter in the template as this is what calls the embeds module to fetch and
- nest the embed code.
- ``EmbedBlock`` StreamField block type
- -------------------------------------
- The :class:`~wagtail.embeds.block.EmbedBlock` block type allows embeds
- to be placed into a ``StreamField``.
- For example:
- .. code-block:: python
- from wagtail.embeds.blocks import EmbedBlock
- class MyStreamField(blocks.StreamBlock):
- ...
- embed = EmbedBlock()
- ``{% embed %}`` tag
- -------------------
- Syntax: ``{% embed <url> [max_width=<max width>] %}``
- You can nest embeds into a template by passing the URL and an optional
- ``max_width`` argument to the ``{% embed %}`` tag.
- The ``max_width`` argument is sent to the provider when fetching the embed code.
- .. code-block:: html+Django
- {% load wagtailembeds_tags %}
- {# Embed a YouTube video #}
- {% embed 'https://www.youtube.com/watch?v=SJXMTtvCxRo' %}
- {# This tag can also take the URL from a variable #}
- {% embed page.video_url %}
- From Python
- -----------
- You can also call the internal ``get_embed`` function that takes a URL string
- and returns an ``Embed`` object (see model documentation below). This also
- takes a ``max_width`` keyword argument that is sent to the provider when
- fetching the embed code.
- .. code-block:: python
- from wagtail.embeds.embeds import get_embed
- from wagtail.embeds.exceptions import EmbedException
- try:
- embed = get_embed('https://www.youtube.com/watch?v=SJXMTtvCxRo')
- print(embed.html)
- except EmbedException:
- # Cannot find embed
- pass
- .. _configuring_embed_finders:
- Configuring embed "finders"
- ===========================
- Embed finders are the modules within Wagtail that are responsible for producing
- embed code from a URL.
- Embed finders are configured using the ``WAGTAILEMBEDS_FINDERS`` setting. This
- is a list of finder configurations that are each run in order until one of them
- successfully returns an embed:
- The default configuration is:
- .. code-block:: python
- WAGTAILEMBEDS_FINDERS = [
- {
- 'class': 'wagtail.embeds.finders.oembed'
- }
- ]
- .. _oEmbed:
- oEmbed (default)
- ----------------
- The default embed finder fetches the embed code directly from the content
- provider using the oEmbed protocol. Wagtail has a built-in list of providers
- which are all enabled by default. You can find that provider list at the
- following link:
- https://github.com/wagtail/wagtail/blob/master/wagtail/embeds/oembed_providers.py
- .. _customising_embed_providers:
- Customising the provider list
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- You can limit which providers may be used by specifying the list of providers
- in the finder configuration.
- For example, this configuration will only allow content to be nested from Vimeo
- and Youtube. It also adds a custom provider:
- .. code-block:: python
- from wagtail.embeds.oembed_providers import youtube, vimeo
- # Add a custom provider
- # Your custom provider must support oEmbed for this to work. You should be
- # able to find these details in the provider's documentation.
- # - 'endpoint' is the URL of the oEmbed endpoint that Wagtail will call
- # - 'urls' specifies which patterns
- my_custom_provider = {
- 'endpoint': 'https://customvideosite.com/oembed',
- 'urls': [
- '^http(?:s)?://(?:www\\.)?customvideosite\\.com/[^#?/]+/videos/.+$',
- ]
- }
- WAGTAILEMBEDS_FINDERS = [
- {
- 'class': 'wagtail.embeds.finders.oembed',
- 'providers': [youtube, vimeo, my_custom_provider],
- }
- ]
- Customising an individual provider
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Multiple finders can be chained together. This can be used for customising the
- configuration for one provider without affecting the others.
- For example, this is how you can instruct Youtube to return videos in HTTPS
- (which must be done explicitly for YouTube):
- .. code-block:: python
- from wagtail.embeds.oembed_providers import youtube
- WAGTAILEMBEDS_FINDERS = [
- # Fetches YouTube videos but puts ``?scheme=https`` in the GET parameters
- # when calling YouTube's oEmbed endpoint
- {
- 'class': 'wagtail.embeds.finders.oembed',
- 'providers': [youtube],
- 'options': {'scheme': 'https'}
- },
- # Handles all other oEmbed providers the default way
- {
- 'class': 'wagtail.embeds.finders.oembed',
- }
- ]
- .. topic:: How Wagtail uses multiple finders
- If multiple providers can handle a URL (for example, a YouTube video was
- requested using the configuration above), the topmost finder is chosen to
- perform the request.
- Wagtail will not try to run any other finder, even if the chosen one didn't
- return an embed.
- .. _facebook_and_instagram_embeds:
- Facebook and Instagram
- ----------------------
- As of October 2020, Facebook deprecated their public oEmbed APIs. If you would
- like to embed Facebook or Instagram posts in your site, you will need to
- use the new authenticated APIs. This requires you to set up a Facebook
- Developer Account and create a Facebook App that includes the oEmbed Product.
- Instructions for creating the neccessary app are in the requirements sections of the
- `Facebook <https://developers.facebook.com/docs/plugins/oembed>`_
- and `Instagram <https://developers.facebook.com/docs/instagram/oembed>`_ documentation.
- Once you have your app access tokens (App ID and App Secret), add the Facebook and/or
- Instagram finders to your ``WAGTAILEMBEDS_FINDERS`` setting and configure them with
- the App ID and App Secret from your app:
- .. code-block:: python
- WAGTAILEMBEDS_FINDERS = [
- {
- 'class': 'wagtail.embeds.finders.facebook',
- 'app_id': 'YOUR FACEBOOK APP_ID HERE',
- 'app_secret': 'YOUR FACEBOOK APP_SECRET HERE',
- },
- {
- 'class': 'wagtail.embeds.finders.instagram',
- 'app_id': 'YOUR INSTAGRAM APP_ID HERE',
- 'app_secret': 'YOUR INSTAGRAM APP_SECRET HERE',
- }
- ]
- By default, Facebook and Instagram embeds include some JavaScript that is necessary to
- fully render the embed. In certain cases, this might not be something you want - for
- example, if you have multiple Facebook embeds, this would result in multiple script tags.
- By passing ``'omitscript': True`` in the configuration, you can indicate that these script
- tags should be omitted from the embed HTML. Note that you will then have to take care of
- loading this script yourself.
- .. _Embedly:
- Embed.ly
- --------
- `Embed.ly <https://embed.ly>`_ is a paid-for service that can also provide
- embeds for sites that do not implement the oEmbed protocol.
- They also provide some helpful features such as giving embeds a consistent look
- and a common video playback API which is useful if your site allows videos to
- be hosted on different providers and you need to implement custom controls for
- them.
- Wagtail has built in support for fetching embeds from Embed.ly. To use it,
- first pip install the ``Embedly`` `python package <https://pypi.org/project/Embedly/>`_.
- Now add an embed finder to your ``WAGTAILEMBEDS_FINDERS`` setting that uses the
- ``wagtail.embeds.finders.oembed`` class and pass it your API key:
- .. code-block:: python
- WAGTAILEMBEDS_FINDERS = [
- {
- 'class': 'wagtail.embeds.finders.embedly',
- 'key': 'YOUR EMBED.LY KEY HERE'
- }
- ]
- .. _custom_embed_finders:
- Custom embed finder classes
- ---------------------------
- For complete control, you can create a custom finder class.
- Here's a stub finder class that could be used as a skeleton; please read the
- docstrings for details of what each method does:
- .. code-block:: python
- from wagtail.embeds.finders.base import EmbedFinder
- class ExampleFinder(EmbedFinder):
- def __init__(self, **options):
- pass
- def accept(self, url):
- """
- Returns True if this finder knows how to fetch an embed for the URL.
- This should not have any side effects (no requests to external servers)
- """
- pass
- def find_embed(self, url, max_width=None):
- """
- Takes a URL and max width and returns a dictionary of information about the
- content to be used for embedding it on the site.
- This is the part that may make requests to external APIs.
- """
- # TODO: Perform the request
- return {
- 'title': "Title of the content",
- 'author_name': "Author name",
- 'provider_name': "Provider name (eg. YouTube, Vimeo, etc)",
- 'type': "Either 'photo', 'video', 'link' or 'rich'",
- 'thumbnail_url': "URL to thumbnail image",
- 'width': width_in_pixels,
- 'height': height_in_pixels,
- 'html': "<h2>The Embed HTML</h2>",
- }
- Once you've implemented all of those methods, you just need to add it to your
- ``WAGTAILEMBEDS_FINDERS`` setting:
- .. code-block:: python
- WAGTAILEMBEDS_FINDERS = [
- {
- 'class': 'path.to.your.finder.class.here',
- # Any other options will be passed as kwargs to the __init__ method
- }
- ]
- The ``Embed`` model
- ===================
- .. class:: wagtail.embeds.models.Embed
- Embeds are fetched only once and stored in the database so subsequent requests
- for an individual embed do not hit the embed finders again.
- .. attribute:: url
- (text)
- The URL of the original content of this embed.
- .. attribute:: max_width
- (integer, nullable)
- The max width that was requested.
- .. attribute:: type
- (text)
- The type of the embed. This can be either 'video', 'photo', 'link' or 'rich'.
- .. attribute:: html
- (text)
- The HTML content of the embed that should be placed on the page
- .. attribute:: title
- (text)
- The title of the content that is being embedded.
- .. attribute:: author_name
- (text)
- The author name of the content that is being embedded.
- .. attribute:: provider_name
- (text)
- The provider name of the content that is being embedded.
- For example: YouTube, Vimeo
- .. attribute:: thumbnail_url
- (text)
- a URL to a thumbnail image of the content that is being embedded.
- .. attribute:: width
- (integer, nullable)
- The width of the embed (images and videos only).
- .. attribute:: height
- (integer, nullable)
- The height of the embed (images and videos only).
- .. attribute:: last_updated
- (datetime)
- The Date/time when this embed was last fetched.
- Deleting embeds
- ---------------
- As long as your embeds configuration is not broken, deleting items in the
- ``Embed`` model should be perfectly safe to do. Wagtail will automatically
- repopulate the records that are being used on the site.
- You may want to do this if you've changed from oEmbed to Embedly or vice-versa
- as the embed code they generate may be slightly different and lead to
- inconsistency on your site.
|