基于django的视频点播网站开发-step4-首页功能

news/2024/5/7 18:31:39/文章来源:https://blog.csdn.net/weixin_34025051/article/details/89545575

在本讲中,我们开始首页功能的开发,在开发过程中,大家将会学习到Django中的通用视图类、分页对象paginator以及foreignKey外键的使用。

效果演示

整体功能

大家可先通过 网站演示地址 浏览一下首页的效果。我们首页呢,比较简洁大方,让人一目了然。我这样设计的目的呢,是让大家把精力放到学习django上面来,不必过度关注花哨的页面效果。

我们把首页拆解为4个小的业务模块来开发,分别是:列表显示、分页功能、搜索功能、分类功能。下面我们分别对这四个功能模块进行开发讲解。

开发思路

开发一个功能的基本思路是:先新建应用,然后分析功能涉及到哪些业务,从而分析出需要的数据库字段,然后编写模型,之后就是展示阶段,通过url路由配置视图函数,来将模型里面的数据显示出来。

ok,我们通过命令建立应用,命名为video。执行后,django将为我们新建video文件夹。

python3 manage.py startapp video

下面的功能模块开发都在该应用(video)下进行。

建模型

此处,我们需要建立两个模型,分别是分类表(classification)和视频表(video)。他们是多对一的关系(一个分类对应多个视频,一个视频对应一个分类)。

首先编写Classification表,在model.py下面,我们键入如下代码。
字段有title(分类名称)和status(是否启用)

class Classification(models.Model):list_display = ("title",)title = models.CharField(max_length=100,blank=True, null=True)status = models.BooleanField(default=True)class Meta:db_table = "v_classification"

字段说明

  • title 分类名称。数据类型是CharField,最大长度为max_length=100,允许为空null=True
  • status 是否启用。数据类型是BooleanField,默认为default=True
  • db_table 表名

然后编写Video模型,根据网站业务,我们设置了title(标题)、 desc(描述)、 classification(分类)、file(视频文件)、cover(封面)、status(发布状态)等字段。其中classification是一个ForeignKey外键字段,表示一个分类对应多个视频,一个视频对应一个分类(多对一)

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)create_time = models.DateTimeField(auto_now_add=True, blank=True, max_length=20)

字段说明

  • title 视频标题。数据类型是charField,最大长度为max_length=100,允许为空null=True
  • desc 视频描述。数据类型是charField,最大长度为max_length=255,允许为空null=True
  • file 视频文件地址。数据类型是fileField。其中存的是视频文件的地址,在之后的视频管理中我们将会对视频的上传进行具体的讲解。
  • cover 视频封面。数据类型是ImageField。存储目录为upload_to='cover/',允许为空null=True
  • status 视频状态。是一个选择状态,用choices设置多选元祖。
  • create_time 创建时间。数据类型是DateTimeField 。设置自动生成时间auto_now_add=True

ForeignKey 表明一种一对多的关联关系。比如这里我们的视频和分类的关系,一个视频只能对应一个分类,而一个分类下可以有多个视频。

更多关于ForeinkKey的说明,可以参看 ForeignKey官方介绍

列表显示

要想访问到首页,必须先配置好路由。在video下建立urls.py文件,写入如下代码

from django.urls import path
from . import viewsapp_name = 'video'
urlpatterns = [path('index', views.IndexView.as_view(), name='index'),
]

一条path语句就代表一条路由信息。这样我们就可以在浏览器输入127.0.0.1:8000/video/index来访问首页了。

显示列表数据非常简单,我们使用django中内置的视图模版类ListView来显示,首先在view.py中编写IndexView类,用它来显示列表数据。键入如下代码

class IndexView(generic.ListView):model = Videotemplate_name = 'video/index.html'context_object_name = 'video_list'  

此处,我们使用了django提供的通用视图类ListView, ListView使用很简单,只需要我们简单的配置几行代码,即可将数据库里面的数据渲染到前端。比如上述代码中,我们配置了

  • model = Video, 作用于Video模型
  • template_name = 'video/index.html' ,告诉ListView要使用我们已经创建的模版文件。
  • context_object_name = 'video_list' ,上下文变量名,告诉ListView,在前端模版文件中,可以使用该变量名来展现数据。

之后,我们在templates文件夹下,建立video目录,用来存放视频相关的模板文件,首先我们创建首页文件index.html。并将刚才获取到的数据显示出来。

<div class="ui grid">{% for item in video_list %}<div class="four wide column"><div class="ui card"><a class="image">{% thumbnail item.cover "300x200" crop="center" as im %}<img class="ui image" src="{{ im.url }}">{% empty %}{% endthumbnail %}<i class="large play icon v-play-icon"></i></a><div class="content"><a class="header">{{ item.title }}</a><div class="meta"><span class="date">发布于{{ item.create_time|time_since}}</span></div><div class="description">{{ item.view_count}}次观看</div></div></div></div>{% empty %}<h3>暂无数据</h3>{% endfor %}
</div>

通过for循环,将video_list渲染到前端。这里我们使用到了django中的内置标签,比如for语句、empty语句。这些都是django中非常常用的语句。在之后的教程中我们会经常遇到。

另外,还使用了thumbnail标签来显示图片,thumbnail是一个很常用的python库,常常被用来做图片显示。

显示结果如下
首页展示

分类功能

在写分类功能之前,我们先学习一个回调函数 get_context_data() 这是ListView视图类中的一个函数,在 get_context_data() 函数中,可以传一些额外内容到模板。因此我们可以使用该函数来传递分类数据。

要使用它,很简单。

只需要在IndexView类下面,追加get_context_data()的实现即可。

class IndexView(generic.ListView):model = Videotemplate_name = 'video/index.html'context_object_name = 'video_list' def get_context_data(self, *, object_list=None, **kwargs):context = super(IndexView, self).get_context_data(**kwargs)classification_list = Classification.objects.filter(status=True).values()context['classification_list'] = classification_listreturn context

在上述代码中,我们将分类数据通过Classification.objects.filter(status=True).values()从数据库里面过滤出来,然后赋给classification_list,最后放到context字典里面。

在前端模板(templates/video/index.html)中,就可以通过classification_list来取数据。添加代码

<div class="classification"><a class="ui red label" href="">全部</a>{% for item in classification_list %}<a class="ui label" href="">{{ item.title }}</a>{% endfor %}
</div>

显示效果如下

当然现在只是实现了分类展示效果,我们还需要继续实现点击效果,即点击不同的分类,显示不同的视频列表。

我们先给每个分类按钮加上href链接

<div class="classification"><a class="ui red label" href="{% url 'home' %}">全部</a>{% for item in classification_list %}<a class="ui label" href="?c={{ item.id }}">{{ item.title }}</a>{% endfor %}
</div>

通过添加?c={{ item.id }} 这里用c代表分类的id,点击后,会传到视图类中,在视图类中,我们使用 get_queryset() 函数,将get数据取出来。通过self.request.GET.get("c", None) 赋给c,判断c是否为None,如果为None,就响应全部,如果有值,就通过get_object_or_404(Classification, pk=self.c)先获取当前类,然后classification.video_set获取外键数据。

    def get_queryset(self):self.c = self.request.GET.get("c", None)if self.c:classification = get_object_or_404(Classification, pk=self.c)return classification.video_set.all().order_by('-create_time')else:return Video.objects.filter(status=0).order_by('-create_time')

更多关于ForeignKey的使用方法,可参考 这里

分页功能

在Django中,有现成的分页解决方案,我们开发者省了不少事情。如果是简单的分页,只需要配置一下paginate_by即可实现。

class IndexView(generic.ListView):model = Videotemplate_name = 'video/index.html'context_object_name = 'video_list'paginate_by = 12c = None
  • painate_by = 12每页显示12条

这样每页的分页数据就能正确的显示出来来,现在来完善底部的页码条。

页码列表需要视图类和模板共同来完成,我们先来写视图类。在前面我们已经写过get_context_data了,该函数的主要功能就是传递额外的数据给模板。这里,我们就利用get_context_data来传递页码数据。

我们先定义一个工具函数,叫get_page_list。 在项目根目录下,新建一个文件helpers.py该文件当作一个全局的工具类,用来存放各种工具函数。把get_page_list放到helpers.py里面 该函数用来生产页码列表,不但这里可以使用,以后在其他地方也可以调用该函数。

def get_page_list(paginator, page):page_list = []if paginator.num_pages > 10:if page.number <= 5:start_page = 1elif page.number > paginator.num_pages - 5:start_page = paginator.num_pages - 9else:start_page = page.number - 5for i in range(start_page, start_page + 10):page_list.append(i)else:for i in range(1, paginator.num_pages + 1):page_list.append(i)return page_list

分页逻辑:

if 页数>=10:当前页<=5时,起始页为1当前页>(总页数-5)时,起始页为(总页数-9)其他情况 起始页为(当前页-5)

举例:

假设一共16页
情况1: 当前页==5  则页码列表为[1,2,3,4,5,6,7,8,9,10]
情况2: 当前页==8  则页码列表为[3,4,5,6,7,8,9,10,11,12]
情况3: 当前页==15 则页码列表为[7,8,9,10,11,12,13,14,15,16]

当然你看到这个逻辑会有点乱,建议大家读着代码,多试验几遍。

当拿到页码列表,我们继续改写get_context_data()函数。 将获取到的classification_list追加到context字典中。

    def get_context_data(self, *, object_list=None, **kwargs):context = super(IndexView, self).get_context_data(**kwargs)paginator = context.get('paginator')page = context.get('page_obj')page_list = get_page_list(paginator, page)classification_list = Classification.objects.filter(status=True).values()context['c'] = self.ccontext['classification_list'] = classification_listcontext['page_list'] = page_listreturn context

你或许对 paginator = context.get('paginator') page = context.get('page_obj')这两行代码感到陌生,我们只需要知道context.get('page_obj')返回的是当前页码,context.get('paginator')返回的是分页对象,就够了。更加详细的介绍,可参考官方。

当数据传递给模板之后,模板就负责显示出来就行了。

因为分页功能比较常用,所以需要把它单独拿出来封装到一个单独的文件中,我们新建templates/base/page_nav.html文件。然后在index.html里面我们将该文件include进来。

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

打开page_nav.html,写入代码

{% if is_paginated %}
<div class="video-page"><div class="ui circular labels">{% if page_obj.has_previous %}<a class="ui circular label" href="?page={{ page_obj.previous_page_number }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">&lt;</a>{% endif %}{% for i in page_list %}{% if page_obj.number == i %}<a class="ui red circular label">{{ i }}</a>{% else %}<a class="ui circular label" href="?page={{ i }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">{{ i }}</a>{% endif %}{% endfor %}{% if page_obj.has_next %}<a class="ui circular label" href="?page={{ page_obj.next_page_number }}{% if c %}&c={{c}}{% endif %}{% if q %}&q={{q}}{% endif %}">&gt;</a>{% endif %}</div>
</div>
{% endif %}

上面代码中,我们用到了page_obj对象的几个属性:has_previous、previous_page_number、next_page_number。通过这几个属性,即可实现复杂的页码显示效果。其中我们还这href里面加了

{% if c %}&c={{c}}

代表分类的id。

搜索功能

要实现搜索,我们需要一个搜索框

因为搜索框是很多页面都需要的,所以我们把代码写到templates/base/header.html文件里面。

<div class="ui small icon input v-video-search"><input class="prompt" value="{{ q }}" type="text" placeholder="搜索视频" id="v-search"><i id="search" class="search icon" style="cursor:pointer;"></i>
</div>

点击搜索或回车的代码写在了static/js/header.js里面。

我们还需要配置一下路由,添加一行搜索的路由。

app_name = 'video'
urlpatterns = [path('index', views.IndexView.as_view(), name='index'),path('search/', views.SearchListView.as_view(), name='search'),
]

搜索路由指向的视图类为SearchListView

下面我们来写SearchListView的代码

class SearchListView(generic.ListView):model = Videotemplate_name = 'video/search.html'context_object_name = 'video_list'paginate_by = 8q = ''def get_queryset(self):self.q = self.request.GET.get("q","")return Video.objects.filter(title__contains=self.q).filter(status=0)def get_context_data(self, *, object_list=None, **kwargs):context = super(SearchListView, self).get_context_data(**kwargs)paginator = context.get('paginator')page = context.get('page_obj')page_list = get_page_list(paginator, page)context['page_list'] = page_listcontext['q'] = self.qreturn context

关键代码就是Video.objects.filter(title__contains=self.q).filter(status=0)
title__contains是包含的意思,表示查询title包含q的记录。利用filter将数据过滤出来。这里写了两层过滤,第一层过滤搜索关键词,第二层过滤status已发布的视频。

另外,这里也用到了get_context_data来存放额外的数据,包括分页数据、q关键词。

配置模板文件是templates/video/search.html

因此模板代码写在search.html里面

<div class="ui unstackable items">{% for item in video_list %}<div class="item"><div class="ui tiny image">{% thumbnail item.cover "300x200" crop="center" as im %}<img class="ui image" src="{{ im.url }}">{% empty %}{% endthumbnail %}</div><div class="middle aligned content"><a class="header" href="{% url 'video:detail' item.pk %}">{{ item.title }}</a></div></div>{% empty %}<h3>暂无数据</h3>{% endfor %}</div>{% include "base/page_nav.html" %}

搜索功能效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_795724.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

连接云服务器_Windows server 2012 云服务器建站教程 (1):远程连接桌面+IIS服务器安装...

服务器&#xff1a;Windows server 2012 阿里云服务器发布网站的过程中&#xff0c;实在是踩了太多的坑了&#xff0c;通过云服务器发布一个http://asp.net真是费劲儿&#xff0c;如果你要是需要访问cshtml格式的网站&#xff0c;会更加费劲儿一点。1.使用远程桌面连接云服务器…

大型网站技术架构(六)网站的伸缩性架构

2019独角兽企业重金招聘Python工程师标准>>> 网站系统的伸缩性架构最重要的技术手段就是使用服务器集群功能&#xff0c;通过不断地向集群中添加服务器来增强整个集群的处理能力。“伸”即网站的规模和服务器的规模总是在不断扩大。 1、网站架构的伸缩性设计 网站的…

linux samba启动连接不上,CentOS中Samba配置后始终连不上解决_Linux教程_Linux公社-Linux系统门户网站 正解...

按照网上的办法改了/etc/samba/smb.conf配置文件&#xff0c;结果在Win7里面就是连不上&#xff0c;后来发现是防火墙的问题。有两个命令必须要执行&#xff1a;1、将SELinux设置成disabled或者permissivesetenforce 02、关闭防火墙服务service iptables stop若SElinux啟用中&a…

php网站在哪儿添加文章_php添加文章时生成静态HTML文章的实现代码

PHP生成静态文章HTML,有批量的生成&#xff0c;但比较标准的应该是在添加文章时就生成HTML文章&#xff0c;编辑时再重新生成HTML文章&#xff0c;删除文章时同样也样删除多余出来的HTML文章&#xff0c;这时批量生成就显得有点力不从心了&#xff0c;下面就介绍一下PHP在添加文…

php多网址文章发布,如何设置发布到多个网站-批量发布文章到站群

软件自定义API接口发布&#xff0c;是针对所有网站类型的发布方法&#xff0c;是最灵活的一种发布模式&#xff0c;当你的网站没有软件上的那几个常用网站程序&#xff0c;就可以考虑这种方法了&#xff0c;此方法通用&#xff0c;但是也需要一定的编程知识。下面跟我一步步设置…

怎么测试本地网页在不同分辨率下电脑显示效果_好的响应式网站应该怎么做?...

响应式网站设计开发&#xff0c;也有叫做响应的Web设计&#xff0c;或着叫响应式网页设计&#xff0c;响应式网站设计开发的目的是为不同设备提供的多种适配的展现形式。一个网站&#xff0c;为了适应不同的用户的不同客户端的查看&#xff0c;通过响应式网站制作过程提供各种适…

jquery导入数据_【Python成长之路】从 零做网站开发 -- 基于Flask和JQuery,实现表格管理平台...

【写在前面】你要开发网站&#xff1f; 嗯。。会Flask吗&#xff1f; 什么东西&#xff0c;没听过。。。会JQuery吗&#xff1f; 是python的库吗 &#xff1f;那你会什么&#xff1f; 我会F12打开网站好吧&#xff0c;那我们来写个简单的表格管理平台。基于Flask框架和JQuery实…

web前端项目实例网站_推荐一个前端开源项目 CDN网站

前面学习到什么是CDN&#xff0c;全称是Content Delivery Network&#xff0c;即内容分发网络。CDN的通俗理解就是网站加速&#xff0c;CPU均衡负载。CDN的基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节&#xff0c;使内容传输的更快、更稳定&#…

win10打不开网络上的计算机,[pc玩家]Windows10中打不开网站的问题怎么解决?

当用户在浏览器中输入网站的域名时&#xff0c;此时将发送请求到DNS服务器以识别连接到该主机名的IP地址&#xff0c;只有正确解析了IP地址才会打开你想要访问的网站。但有时你会收到一个错误消息&#xff0c;告诉你DNS服务器没有响应。要解决这个问题&#xff0c;你可以尝试几…

有域名有服务器没有网站可以备案吗,只有域名没有服务器可以备案吗

只有域名没有服务器可以备案吗 内容精选换一换成功访问网站包含以下两个阶段&#xff0c;这两个阶段缺一不可&#xff0c;需要同时成功才能正常访问网站&#xff0c;如图1所示。阶段一&#xff1a;DNS根据访问请求中的域名解析出对应的IP地址。阶段二&#xff1a;访问网站服务器…

js将图片转换为base64_为网站添加图片 WebP 自动转换功能

最近这几天在网上闲逛时&#xff0c;发现了一个名叫 WebP_Server_Go 的新项目&#xff0c;可以无缝将网站上已有图片转换为 WebP 格式输出&#xff0c;同时不改变原始图片链接&#xff0c;看起来挺适合我个人博客的需求&#xff0c;使用也比较简单。网站使用 WebP 格式图片的好…

为什么linux访问不到文件夹,laravel部署到linux,将public文件夹指定为网站根目录,但是无法访问其子文件夹...

本机使用的是window环境,一切正常,但是部署到linux系统上(配的是nginx),在访问的时候,控制器和方法都能正常执行,页面也可以输出,但是输出的页面却缺少css文件,一查是500错误,已经将请求重定向到public文件夹下,我的目录结构是:public/web/css/css.css域名是:aaa.com直接访问aa…

seo自动发外链_seo如何做外链(做seo外链建设有哪些原则)

人人做seo都需要发外链&#xff0c;同样的工作最终的结果却是千差万别&#xff0c;有些人发的外链让网站优化的结果更好&#xff0c;有些人发外链带给网站的优化结果是无效甚至于是反作用的。我们seo如何做外链呢&#xff1f;做外链建设有哪些原则&#xff1f;一、发布一些高质…

个6000常用wifi弱口令._Python网站开发怎么学(9个练习项目)

> 公众号回复"Python"获取更多学习资源&#xff1b;1. CSS3 基础入门地址: https://www.shiyanlou.com/courses/1246学习人数: 710关注人数: 71该课程已升级&#xff0c;请学习《CSS3 简明教程》&#xff1a;https://www.shiyanlou.com/courses/12372. Java 简明教…

网站封装单个exe_如何测试React网站和应用程序

通过学习测试React网站和应用程序来获取可用于生产的代码。#react#如何测试React网站和应用程序(图片来源&#xff1a;未来)如果您想知道如何测试React&#xff0c;那么您来对地方了。您真的知道您的代码可以执行它的工作吗&#xff1f;您是否在浏览器中测试过&#xff1f;如果…

python建站与java建站有何不同_模板建站好不好?和定制建站有何不同?

很多新手在建站前&#xff0c;都拿不准到底是使用模板建站好&#xff0c;还是找外包团队定制开发好。这两种建站方法差异还是蛮大的&#xff0c;下面就给大家说说模板和定制的几个主要不同之处&#xff0c;你可以根据这些来判断适合自己的建站方式&#xff1a;1.制作周期不同定…

html5网站访问地图

这个地图是我结合了网上的代码自己修改了下做出来的&#xff0c;样子大概是这样 前端使用的是layui&#xff0c;如果要使用的话需要更改一下 我就直接上代码吧 <!DOCTYPE html> <html xmlns"http://www.w3.org/1999/xhtml"> <head><meta char…

wordpressQQ登陆php代码_实现 WordPress 登录查看网站

下面由WordPress教程栏目给大家介绍WordPress 登录查看网站的方法&#xff0c;希望对需要的朋友有所帮助&#xff01;如网站内容只希望注册用户浏览&#xff0c;对其他所有人隐藏&#xff0c;浏览者未登录访问直接跳转到登录注册页面&#xff0c;可以用下面的代码实现。将下面代…

十个网页html,10 个不错的 HTML5 类型网站

Agent 008 Ball 一款采用canvas和audio元素的在线桌球游戏网站The Wilderness Down Town是一个很酷的结合地图和音乐创造出来的互动式电影短片网站。这个由Chris Milk拍摄的基于html5的互动电影短片“We Used to Wait”&#xff0c;超越flash/java,非常强大。网站利用谷歌浏览器…

网站根目录打不开服务器拒绝,检查网站打不开的三种原因

自己做了网站之后&#xff0c;如果在实际访问中&#xff0c;出现了网站打不开的情况&#xff0c;怎么去查找什么原因导致了网站打不开呢&#xff1f;可以通过下面三个方面去检查一下到底自己做网站时哪里出现了问题。一、检查网站域名是否出问题。网站在线方式有二种&#xff1…