Blog Django

wordpress to django : enabling oembed

I recently migrated a number of WordPress blog to django+mezzanine. There's a number of hiccups but I take them as a challenge and opportunity to learn. Case in point is the oembed. In WordPress, this is supported by default. In Django, it's either you use the many oEmbed packages or code your own. Unfortunately, the packages available usually does not fit my use case or too bloated.

First, please understand that I don't intend to rewrite all the migrated posts. Even this very blog has 200 posts in it and I get no time to rewrite them. So the best thing to do IMO, is to replicate things WordPress usually do.

So, I create a new templatetag to filter the content. My use case is limited to videos from YouTube and Vimeo so this is only applicable for them. If need be, just add sources in the patters variable.

from django import template
from django.template.defaultfilters import stringfilter
from mezzanine.blog.models import BlogPost

import json
import re
import requests
from urllib.parse import quote_plus

register = template.Library()

@register.filter(is_safe=True)
@stringfilter
def oembed(content):
    patterns = (
        ('http://www.youtube.com/oembed?format=json&url=',
            re.compile("https?:\/\/(www\.)?youtu(\.be|be\.com\/watch)[\?=\w.@+-]+")),
        ('https://vimeo.com/api/oembed.json?url=',
            re.compile("https?:\/\/(www\.)?vimeo\.com\/[\d]+"))
    )
    for p in patterns:
        for match in re.finditer(p[1], content):
            match_text = match.group()
            url = "%s%s"%(p[0], quote_plus(match_text))
            resp = requests.get(url)
            if resp.status_code == requests.codes.ok:
                data = json.loads(resp.text)
                replace_text = "<div class='%s'> %s</div>"%(data['type'], data['html'])
                content = content.replace(match_text, replace_text)

    return content

Usage

{{ blog_post.content|safe|oembed }}

Note that the filter oembed. You can download the snippet from my GitHub Gist. I won't be able to maintain this so I did not create a project. But you are free to copy it in case you need it.

Bonus - AutoFit the Video Embed

If you notice, the video does not auto-fit to its container. It is embedded based on the HTML that's supplied by the source. Thankfully, fitvid can help with that. It's a lightweight jQuery plugin for fluid video width. Download a copy of from GitHub and place it in your static folder.

I called it at the footer section.

{% block footer_scripts %}
<script type="text/javascript" src="{% static 'js/fitvids.js' %}"></script>
<script type="text/javascript">
    $('.video').fitVids();
</script>
{% endblock footer_scripts %}

Now, the next annoying problem I have to deal with is the [gallery]. Oh well, let's take it one a a time then. That would be for another post.