基于django的视频点播网站开发-step7-我的收藏喜欢功能

从本讲起,我们会讲到个人菜单中另外两个比较重要的功能,“我的收藏”与“我的喜欢”。感兴趣的同学可以点击网站的右上角,即可弹出个人菜单,你就能看到“我的收藏”与“我的喜欢”了。通过学习这两个功能,我们会加深对django中通用视图类的理解与应用。

Demo预览

我的收藏

我们先来讨论模型,我们分析一下,我收藏的视频与我喜欢的视频,其中的视频都是属于video模型,因此我们应该在video模型上进行修改。因为是我的收藏我的喜欢,都是与关联,又因为,我可以收藏多个视频,视频也可以被多个用户收藏,所以用户与视频是属于多对多的关系。所以我们在video模型上添加两个字段liked和collected,分别对应我喜欢和我收藏。代码如下

代码语言:txt
复制
class Video(models.Model):
    STATUS_CHOICES = (
        ('0', '发布中'),
        ('1', '未发布'),
    )
    title = models.CharField(max_length=100,blank=True, null=True)
    desc = models.CharField(max_length=255,blank=True, null=True)
    classification = models.ForeignKey(Classification, on_delete=models.CASCADE, null=True)
    file = models.FileField(max_length=255)
    cover = models.ImageField(upload_to='cover/',blank=True, null=True)
    status = models.CharField(max_length=1 ,choices=STATUS_CHOICES, blank=True, null=True)
    view_count = models.IntegerField(default=0, blank=True)
    liked = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                   blank=True, related_name="liked_videos")
    collected = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                   blank=True, related_name="collected_videos")
    create_time = models.DateTimeField(auto_now_add=True, blank=True, max_length=20)

可以看出liked和collected字段都是属于ManyToManyField类型,表示视频与用户是多对多的关系。并分别设置它们的别名为"liked_videos"和"collected_videos",有django基础的同学应该明白,通过别名也可以访问到数据。

下面我们来添加两者的路由,添加在users/urls.py下面。

代码语言:txt
复制
path('<int:pk>/collect_videos/', views.CollectListView.as_view(), name='collect_videos'),
path('<int:pk>/like_videos/', views.LikeListView.as_view(), name='like_videos'),

其中,我的收藏的视图类是CollectListView,我的喜欢的视图类是LikeListView。我们先来实现CollectListView

代码语言:txt
复制
class CollectListView(generic.ListView):
    model = User
    template_name = 'users/collect_videos.html'
    context_object_name = 'video_list'
    paginate_by = 10
def get_context_data(self, *, object_list=None, **kwargs):
    context = super(CollectListView, self).get_context_data(**kwargs)
    paginator = context.get(&#39;paginator&#39;)
    page = context.get(&#39;page_obj&#39;)
    page_list = get_page_list(paginator, page)
    context[&#39;page_list&#39;] = page_list
    return context
def get_queryset(self):
    user = get_object_or_404(User, pk=self.kwargs.get(&#39;pk&#39;))
    videos = user.collected_videos.all()
    return videos</code></pre></div></div><p>与首页展示的功能类似,这里同样继承了ListView通用视图类。并使用了公共函数get_page_list对数据进行分页。在获取收藏数据列表时,我们用的是user.collected_videos.all(),其中collected_videos就是前面定义的别名。 并通过配置template_name将数据传递给模板文件users/collect_videos.html。</p><p>模板文件关键代码</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>txt</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-txt"><code class="language-txt" style="margin-left:0">&lt;h3 class=&#34;ui header&#34;&gt;我的收藏&lt;/h3&gt;

<div class="ui unstackable items">

{% for item in video_list %}
&lt;div class=&#34;item&#34;&gt;
    &lt;div class=&#34;ui tiny image&#34;&gt;
        {% thumbnail item.cover &#34;300x200&#34; crop=&#34;center&#34; as im %}
        &lt;img class=&#34;ui image&#34; src=&#34;{{ im.url }}&#34;&gt;
        {% empty %}
        {% endthumbnail %}
    &lt;/div&gt;
    &lt;div class=&#34;middle aligned content&#34;&gt;
        &lt;a class=&#34;header&#34; href=&#34;{% url &#39;video:detail&#39; item.pk %}&#34;&gt;{{ item.title }}&lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;
{% empty %}
&lt;h3&gt;暂无数据&lt;/h3&gt;
{% endfor %}

</div>

{% include "base/page_nav.html" %}

最终展示效果

我的喜欢

下面来开发我的喜欢功能

该功能与我的收藏功能类似。因为前面已经添加了like_videos路由,我们直接写LikeListView的代码

代码语言:txt
复制
class LikeListView(generic.ListView):
model = User
template_name = 'users/like_videos.html'
context_object_name = 'video_list'
paginate_by = 10

def get_context_data(self, *, object_list=None, **kwargs):
    context = super(LikeListView, self).get_context_data(**kwargs)
    paginator = context.get(&#39;paginator&#39;)
    page = context.get(&#39;page_obj&#39;)
    page_list = get_page_list(paginator, page)
    context[&#39;page_list&#39;] = page_list
    return context

def get_queryset(self):
    user = get_object_or_404(User, pk=self.kwargs.get(&#39;pk&#39;))
    videos = user.liked_videos.all()
    return videos</code></pre></div></div><p>与我的收藏的模式一模一样,同样是继承ListView并设置相关model与template_name变量。最终通过users/like_videos.html来渲染。</p><p>like_videos.html关键代码</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>txt</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-txt"><code class="language-txt" style="margin-left:0">&lt;h3 class=&#34;ui header&#34;&gt;我的喜欢&lt;/h3&gt;

<div class="ui unstackable items">

{% for item in video_list %}
&lt;div class=&#34;item&#34;&gt;
    &lt;div class=&#34;ui tiny image&#34;&gt;
        {% thumbnail item.cover &#34;300x200&#34; crop=&#34;center&#34; as im %}
        &lt;img class=&#34;ui image&#34; src=&#34;{{ im.url }}&#34;&gt;
        {% empty %}
        {% endthumbnail %}
    &lt;/div&gt;
    &lt;div class=&#34;middle aligned content&#34;&gt;
        &lt;a class=&#34;header&#34; href=&#34;{% url &#39;video:detail&#39; item.pk %}&#34;&gt;{{ item.title }}&lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;
{% empty %}
&lt;h3&gt;暂无数据&lt;/h3&gt;
{% endfor %}

</div>

{% include "base/page_nav.html" %}

最终展示效果