Media plugins - Vlog / Podcast

Publising a vlog or a podcast require more introspection on the plugin contents than is generally available to django CMS plugins.

djangocms-blog provides a mixin for plugin models and templatetags to help when dealing with this use case.

For convenience, an additional media placeholder has been added to the Post model.

Note

djangocms-blog only provide a generic interface to introspect media plugins but it does not provide any plugin for any media platform as they would be very hard to maintain as the platforms changes. Examples provided here are working at the time of writing but they may require changes to work.

Base classes

class djangocms_blog.media.base.MediaAttachmentPluginMixin

Base class for media-enabled plugins.

Items that needs implementation in subclasses:

  • media_id: property that provides the object id on the external platform

  • media_url: property that provides the media public URL

  • _media_autoconfiguration: configuration dictionary (see documentation for details)

_media_autoconfiguration = {'callable': None, 'main_url': '', 'params': [], 'thumb_url': ''}

Configuration dictionary. All the keys are required:

  • 'params': one or more regular expressions to retrieve the media ID according to the provided media_url. It must contain a capturing group called media_id (see examples below).

  • 'thumb_url': URL of the intermediate resolution media cover (depending on the plaform). It supports string formatting via format by providing the return json for the media according to the plugic specification.

  • 'main_url': URL of the maximum resolution media cover (depending on the plaform). It supports string formatting via %-formatting by providing the return json for the media according to the plugic specification.

  • 'callable': in case the above information are not recoverable from the object URL, provide here the name of a method on the plugin model instance taking the media_id as parameter and that builds the data required by thumb_url, media_url strings to build the correct cover urls.

get_main_image()

URL of the media cover at maximum resolution

Return type:

str

get_thumb_image()

URL of the media cover at intermediate resolution

Return type:

str

property media_id

ID of the object on the remote media.

Return type:

str

property media_params

Retrieves the media information.

Minimal keys returned:

  • media_id: object id on the external platform

  • url: full url to the public version of the media

In case the 'callable' key in py:attr:` _media_autoconfiguration` is not None, it will be called instead (as method on the current model instance) to retrieve the information with any required logic.

Returns:

media information dictionary

Return type:

dict

property media_url

Public URL of the object on the remote media.

As you will likely have a URL on the plugin model, it’s usually enough to return that value, but you are free to implement any way to retrieve it.

Return type:

str

djangocms_blog.templatetags.djangocms_blog.media_images(context, post, main=True)

Extract images of the given size from all the djangocms_blog.media.base.MediaAttachmentPluginMixin plugins in the media placeholder of the provided post.

Support djangocms-video poster field in case the plugin does not implement MediaAttachmentPluginMixin API.

Usage:

Parameters:
Returns:

list of images urls

Return type:

list

djangocms_blog.templatetags.djangocms_blog.media_plugins(context, post)

Extract djangocms_blog.media.base.MediaAttachmentPluginMixin plugins from the media placeholder of the provided post.

They can be rendered with render_plugin templatetag:

Parameters:
Returns:

list of djangocms_blog.media.base.MediaAttachmentPluginMixin plugins

Return type:

List[djangocms_blog.media.base.MediaAttachmentPluginMixin]

How to build the media plugins

  1. Create a plugin model

    Create a plugin model inheriting from CMSPlugin or a subclass of it and add djangocms_blog.media.base.MediaAttachmentPluginMixin mixin.

  2. Provide the media configuration

    Populate djangocms_blog.media.base.MediaAttachmentPluginMixin._media_autoconfiguration.

  3. Implement required properties

    Provide an implementation for the following properties:

  4. Add any additional properties / method suitable for your case.

    See media_title field in the Vimeo model below.

Example

Plugin model

This is a basic example for a Vimeo plugin.

As covers cannot be calculated from the video id, we must download the related json and extract information from there. This model use the 'callable' parameter in djangocms_blog.media.base.MediaAttachmentPluginMixin._media_autoconfiguration

 class Vimeo(MediaAttachmentPluginMixin, CMSPlugin):
     url = models.URLField('Video URL')

     _media_autoconfiguration = {
         'params': [
             re.compile('^https://vimeo.com/(?P<media_id>[-0-9]+)$'),
         ],
         'thumb_url': '%(thumb_url)s',
         'main_url': '%(main_url)s',
         'callable': 'vimeo_data',
     }

     def __str__(self):
         return self.url

     @property
     def media_id(self):
         try:
             return self.media_params['id']
         except KeyError:
             return None

     @property
     def media_title(self):
         try:
             return self.media_params['title']
         except KeyError:
             return None

     @property
     def media_url(self):
         return self.url

     def vimeo_data(self, media_id):
         response = requests.get(
             'https://vimeo.com/api/v2/video/%(media_id)s.json' % {'media_id': media_id, }
         )
         json = response.json()
         data = {}
         if json:
             data = json[0]
             data.update(
                 {
                     'main_url': data['thumbnail_large'],
                     'thumb_url': data['thumbnail_medium'],
                 }
             )
         return data

Plugin class

Plugin class does not require any special code / configuration and can be setup as usual.

 @plugin_pool.register_plugin
 class VimeoPlugin(CMSPluginBase):
     model = Vimeo
     module = 'Media'
     name = 'Vimeo'
     render_template = 'media_app/vimeo.html'

How to display information in templates

The actual implementation may vary a lot according to your design. To ease retrieving the plugins, check djangocms_blog.templatetags.djangocms_blog.media_images() djangocms_blog.templatetags.djangocms_blog.media_plugins() which abstract away a lot of the django CMS logic to retrieve the plugins for a placeholder.

It’s important to remember that at least in some templates, you must have the media placeholder rendered using {% render_placeholder post.media %} templatetag, otherwise you will not be able to add the plugins to the blog post.

Example

Media plugin

The media plugin requires the normal template to render the video according to the plugin fields:

 {% if instance.media_id %}<iframe src="https://player.vimeo.com/video/{{ instance.media_id }}?badge=0&autopause=0&player_id=0&app_id=2221" width="1920" height="1080" frameborder="0" title="{{ instance.media_title }}" allow="autoplay; fullscreen" allowfullscreen></iframe>{% endif %}

Blog posts list

A basic implementation is retrieving the covers associated to each media content via djangocms_blog.templatetags.djangocms_blog.media_images() and rendering each with a <img> tag:

 ...
 {% media_images post as previews %}
 <div class="blog-visual">
   {% for preview in previews %}<img src="{{ preview }}" />{% endfor %}
 </div>
 ...

Blog posts detail

A basic implementation is rendering the media plugins as you would do with normal plugins:

 ...
 {% if not post.main_image_id %}
     <div class="blog-visual">{% render_placeholder post.media %}</div>
 {% else %}
 ...

djangocms-video support

poster attribute from djangocms-video is also supported.

poster is just a static fixed-size image you can set to a djangocms-video instance, but adding the plugin to the media placeholder allows to extract the image from the field and display along with the generated previews by seamlessly using media_images.

The rendering of the full content is of course fully supported.