在Django网页中嵌入来自用户提交的评论的YouTube视频

时间:2017-02-10 18:32:07

标签: django youtube embed jinja2

我正在Django制作一个博客网页,我允许对博客文章发表评论。当用户提交评论时,我可以使用评论模型中的函数来识别他们在文本中包含的链接。我还可以使用iframe和用户在评论中使用的网址列表将视频嵌回到模板中。我遇到的问题是我想要在用户在链接中键入的完全相同的位置显示嵌入的视频。例如,如果用户键入了一段文字,然后粘贴在YouTube链接中,然后又输入了一个段落,我希望将视频嵌入段落之间。我尝试了几件事,但我还没弄清楚。我很感激我得到的任何答案。以下是评论模型的代码:

class Comment(models.Model):

    post = models.ForeignKey('forum.Thread', related_name='comments')
    username = models.CharField(max_length=20,default='guest')
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    approved_comment = models.BooleanField(default=False)

    def approve(self):
        self.approved_comment = True
        self.save()

    def __str__(self):
        return self.text

    def get_youtube_urls(self):
        urls = []
        youtube_regex = (
            r'(https?://)?(www\.)?'
            '(youtube|youtu|youtube-nocookie)\.(com|be)/'
            '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')

        matches = re.findall(youtube_regex, self.text)

        for url in matches:
            urls.append(url[5])

        return urls

以下是我的模板中处理评论的部分:

<div class="comment">
    <strong>Reply from user {{ comment.username }}</strong>
    <p>{{ comment.text|linebreaks|urlize }}</p>
    {% if comment.get_youtube_urls %}
        {% for url in comment.get_youtube_urls %}
            <div style="position:relative;height:0;padding-bottom:56.25%"><iframe src="https://www.youtube.com/embed/{{url}}?ecver=2" width="640" height="360" frameborder="0" style="position:absolute;width:50%;height:50%;left:0" allowfullscreen></iframe></div>
        {% endfor %}
    {% endif %}
    <div class="date">{{ comment.created_date }}</div>
</div>

对于如何将视频嵌入用户在文本中放置链接的人,是否有任何想法?

1 个答案:

答案 0 :(得分:0)

  

之前,我解释过如下,因为我创建了一个问题save regex permalink not work well

因此,如果您想测试它,您可以手动尝试。 我在http://www.pyregex.com上用;

检查你的正则表达式模式

1。模式:findall

2。模式:

(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})

3。测试字符串:

https://youtu.be/yVpbFMhOAwE

https://www.youtube.com/watch?v=8Z5EjAmZS1o

https://www.youtube.com/embed/yVpbFMhOAwE

<iframe width="560" height="315" src="https://www.youtube.com/embed/Tlf00NT6mig" frameborder="0" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/KQzCxdO3hvo" frameborder="0" allowfullscreen></iframe>

https://www.youtube.com/watch?v=VslLZcV9ZcU&list=RD8Z5EjAmZS1o&index=2

4。结果:

["https://","","youtu","be","","yVpbFMhOAwE"]
["https://","www.","youtube","com","watch?v=","8Z5EjAmZS1o"]
["https://","www.","youtube","com","embed/","yVpbFMhOAwE"]
["https://","www.","youtube","com","embed/","Tlf00NT6mig"]
["https://","www.","youtube","com","embed/","KQzCxdO3hvo"]
["https://","www.","youtube","com","watch?v=","VslLZcV9ZcU"]

我认为你应该这样做才能获得视频ID;

def get_youtube_urls(self):

    youtube_regex = (
        r'(https?://)?(www\.)?'
        '(youtube|youtu|youtube-nocookie)\.(com|be)/'
        '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')

    matches = re.findall(youtube_regex, self.text)

    urls = []
    for url in matches:
        id = url[-1]        # from last index of `matches` list.
        if len(id) == 11:   # check if `id` is valid or not.
            urls.append(id)
    return urls

如果它不起作用,我建议您使用此更改上面youtube_regex的值(不保存在元组中)

youtube_regex = r'(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'

# OR, recomended to use this;

youtube_regex = r'http(?:s?):\/\/(?:www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'

更新

为了获得正确的位置,我建议您使用finditer;

>>> youtube_regex = r'http(?:s?):\/\/(?:www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})'
>>> pattern = re.compile(youtube_regex)
>>> [{'origin': m.group(), 'id': m.group(4), 'position': m.start()} for m in pattern.finditer(test_strings) ]
[
  {'position': 0, 'id': 'yVpbFMhOAwE', 'origin': 'https://youtu.be/yVpbFMhOAwE'}, 
  {'position': 30, 'id': '8Z5EjAmZS1o', 'origin': 'https://www.youtube.com/watch?v=8Z5EjAmZS1o'}, 
  {'position': 75, 'id': 'yVpbFMhOAwE', 'origin': 'https://www.youtube.com/embed/yVpbFMhOAwE'}, 
  {'position': 156, 'id': 'Tlf00NT6mig', 'origin': 'https://www.youtube.com/embed/Tlf00NT6mig'}, 
  {'position': 280, 'id': 'KQzCxdO3hvo', 'origin': 'https://www.youtube.com/embed/KQzCxdO3hvo'}, 
  {'position': 366, 'id': 'VslLZcV9ZcU', 'origin': 'https://www.youtube.com/watch?v=VslLZcV9ZcU'}
]
>>

然后,使用templatetags处理它。以下此脚本尚未完成,您需要删除<iframe等标记,或者从原始文本注释中删除..

import re
from django import template
from django.utils.safestring import mark_safe

register = template.Library()

def iframe_video(id):
    """
    return html string iframe video from the `id`.
    """
    return '<iframe src="https://www.youtube.com/embed/{}"></iframe>'.format(id)

@register.filter
def safe_comment(text_comment):
    """
    {{ comment.text|safe_comment|linebreaks|urlize }}
    """
    youtube_regex = (r'http(?:s?):\/\/(?:www\.)?'
                     '(youtube|youtu|youtube-nocookie)\.(com|be)/'
                     '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
    pattern = re.compile(youtube_regex)
    matches = [
        {'origin': m.group(), 'id': m.group(4), 'position': m.start()}
        for m in pattern.finditer(text_comment)
    ]
    for match in matches:
        id = match['id']
        origin = match['origin']
        position = match['position']

        # text_comment.replace(origin, iframe_video(id))
        # do something to replace tag <iframe, or else..
    return mark_safe(text_comment)