Embedding YouTube video
Recently I was working on a project where we wanted to allow users to insert YouTube videos into content on a site. At first, this seemed like a simple issue; allow the user to paste the YouTube embed code into a form and save it into the database. To display it, simply output the embed code directly in the template code and viola.
One of the problems with this approach is trust. Allowing a user to embed data directly into the page this way is obviously a huge security concern. Another issue with this approach is flexibility. We're at the mercy of the embedded code's parameters for display attributes.
So, how do we fix it?
First, a regular expression to validate the input is actually a YouTube ID. The following regular expression should do the trick:
re.compile(r'^[\w-]{11}$|(?<=/v/)[\w-]{11}|(?<=\?v=)[\w-]{11}')
This will match:
* http://www.youtube.com/watch?v=zIV4poUZAQo
* <object width="560" height="340">
<param name="movie"
value="http://www.youtube.com/v/zIV4poUZAQo&hl=en&fs=1"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/zIV4poUZAQo&hl=en&fs=1"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="560" height="340"></embed>
</object>
* zIV4poUZAQo
Second, now that we can extract the ID, don't store anything else. We can always re-construct the embed code ourselves, using the parameters we want.
Here's an example of how you could setup your form's clean_embed_code method:
def clean_embed_code(self):
if self.cleaned_data.get('embed_code'):
embed_code_re = re.compile(r'^\w{11}$|(?<=/v/)\w{11}|(?<=\?v=)\w{11}')
embed_code = embed_code_re.findall(self.cleaned_data['embed_code'])[0]
if embed_code:
return embed_code
raise forms.ValidationError(
_('Please enter a valid YouTube embed code')
)
Finally, now that we know we have a valid ID (and nothing else) in our embed_code field, we can generate the real embed code tag in our template like this:
<object width="560" height="340">
<param name="movie" value="http://www.youtube.com/v/
{{ embedded_object.embed_code }}"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/
{{ embedded_object.embed_code }}"
type="application/x-shockwave-flash"
allowscriptaccess="always"
allowfullscreen="true" width="560" height="340">
</embed>
</object>
An even better solution would be to put the snippet above in a template tag for ease of use. Something like this, would work pretty well, I think:
{% youtube_video embed_code 200x150 %}
Here's the implementation for that:
# templatetags/video_tags.py
@register.inclusion_tag('videos/youtube_video.html')
def youtube_video(embed_code, dimensions):
width, height = dimensions.split('x')
return {
'embed_code': embed_code,
'width': width,
'height': height,
}
And, the template:
{# templates/videos/youtube_video.html #}
<object width="{{ width }}" height="{{ height }}">
<param name="movie" value="http://www.youtube.com/v/{{ embed_code }}">
</param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/{{ embed_code }}"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="{{ width }}" height="{{ height }}">
</embed>
</object>
