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

Embedding YouTube Videos from User Submitted Comments in Django Webpage

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

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>

有没有人对如何在用户将 link 放在文本中的位置嵌入视频有任何想法?

Previously, I explained such as below because I created an issue 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'}
]
>>

然后,用模板标签处理。下面这个脚本还没有完成,你需要删除标签,例如<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)