DJANGO-天天生鲜项目从0到1-008-列表页
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习
https://www.bilibili.com/video/BV1vt41147K8?p=1
列表页
设计URL
列表页层级为/goods/list/goods_type_id,又因为列表页需要分页和排序,因此url需要包括页码信息和排序方式,即/goods/list/goods_type_id/page/sort_method/
为了符合restful规范,即每个url(除了?的参数部分)指向的应该是某个具体的资源,因此url最终设计到/page/结束,因为排序方式只是针对具体的page数据进行展示的顺序不同,数据的内容是一样的,所以排序方式放在get的参数中,即最后url形式为:/goods/list/goods_type_id/page_num?sort='default'
urlpatterns = [
...
path('goods/list/<int:goods_type_id>/<int:page_num>/', ListView.as_view(), name='list'),
...
]
在url.py中包含了两个int类型的参数,?类型的参数是不需要写在url.py中的
排序和分页
编辑view.py文件
# /goods/list/goods_type_id/page_num?sort='default'
class ListView(View):
'''商品列表视图类'''
template_name = 'goods/list.html' def get(self, request, goods_type_id, page_num):
'''显示商品列表'''
# 获取数据信息
# 全部商品分类
all_type = GoodsType.objects.all() # 当前商品类型
try:
goods_type = GoodsType.objects.get(id=goods_type_id)
except GoodsType.DoesNotExist:
return redirect(reverse('goods:index')) # 新品推荐
new_goods = Goods.objects.filter(goodstype=goods_type).order_by('-create_time')[:2] # 商品列表
# 排序方式
sort_dic = {
'price': 'price',
'hot': '-sales',
'default': '-create_time',
}
# 获取url地址中的参数
url_sort = request.GET.get('sort')
# 将url中的排序参数与排序字典匹配,匹配不到则以默认方式
if url_sort in sort_dic:
sort = url_sort
else:
sort = 'default'
# 获取排序字段
order_by = sort_dic.get(sort)
goods_list = Goods.objects.filter(goodstype=goods_type).order_by(order_by) # 分页
# 创建分页对象,每页显示1条记录
paginator = Paginator(goods_list, 1)
# 获取总页数
total_page = paginator.num_pages
# 判断参数的页码是否在分页页码范围内,不在则显示第一页
if page_num > total_page:
page_num = 1
# 当前页的page对象
page = paginator.page(page_num) # 获取显示的页码范围,这里设置只显示三个页码
if total_page <= 3:
# 若总页数小于3,则将页码全部显示
page_list = range(1, total_page+1)
elif page_num == 1:
# 若当前页码为1,则范围为1,2,3
page_list = range(1, 4)
elif page_num == total_page:
# 若当前页码为最后一页,则将最后三个页码全部显示
page_list = range(total_page-2, total_page+1)
else:
# 其他情况则显示前一页,当前页,后一页的页码
page_list = range(page_num-1, page_num+2) # 组织上下文
context = {
'all_type': all_type,
'goods_type': goods_type,
'new_goods': new_goods,
'sort': sort,
'page': page,
'page_list': page_list,
}
return render(request, self.template_name, context)
排序
排序使用?sort='method'参数形式,通过request.GET.get(sort)获取参数的值,预定义三种排序方式,若获取到其他值则认为是以默认形式排序
'default'(默认)字段:create_time
'hot'(人气)字段:sales
'price'(价格)字段:price
对应html内容为:
<div class="sort_bar">
<a href="{% url 'goods:list' goods_type.id 1 %}" {% if sort == 'default' %}class="active"{% endif %}>默认</a>
<a href="{% url 'goods:list' goods_type.id 1 %}?sort=price" {% if sort == 'price' %}class="active"{% endif %}>价格</a>
<a href="{% url 'goods:list' goods_type.id 1 %}?sort=hot" {% if sort == 'hot' %}class="active"{% endif %}>人气</a>
</div>
分页
使用django提供的分页器
1. 通过Paginator(goods_list, 1)创建分页器对象paginator,第一个参数为可迭代对象,第二个参数为每页显示的记录条数
2. 通过分页器对象paginator.page(page_num)获取当前页的page对象
Paginator对象
Paginator类拥有以下方法和属性:
方法:
Paginator.page(number)[source]
返回指定页面的对象列表,比如第7页的所有内容,下标以1开始。如果提供的页码不存在,抛出InvalidPage异常。
属性:
- Paginator.count:所有页面的对象总数。
- Paginator.num_pages:页面总数。
- Paginator.page_range:基于1的页数范围迭代器。
Page对象
Paginator.page()将返回一个Page对象,我们主要的操作都是基于Page对象的,它具有下面的方法和属性:
方法:
- Page.has_next()[source]:如果有下一页,则返回True。
- Page.has_previous()[source]:如果有上一页,返回 True。
- Page.has_other_pages()[source]:如果有上一页或下一页,返回True。
- Page.next_page_number()[source]:返回下一页的页码。如果下一页不存在,抛出InvalidPage异常。
- Page.previous_page_number()[source]:返回上一页的页码。如果上一页不存在,抛出InvalidPage异常。
Page.start_index()[source]
:返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始计数。 比如,将五个对象的列表分为每页两个对象,第二页的start_index()
会返回3。Page.end_index()[source]
:返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。 比如,将五个对象的列表分为每页两个对象,第二页的end_index()
会返回4。
属性:
- Page.object_list:当前页上所有对象的列表。
- Page.number:当前页的序号,从1开始计数。
- Page.paginator:当前Page对象所属的Paginator对象。
html中使用分页
<div class="pagenation">
{% if page.has_previous %}
<a href="{% url 'goods:list' goods_type.id page.previous_page_number %}"><上一页</a>
{% endif %}
{% for num in page_list %}
<a href="{% url 'goods:list' goods_type.id num %}?sort={{ sort }}" {% if num == page.number %}class="active"{% endif %}>{{ num }}</a>
{% endfor %}
{% if page.has_next %}
<a href="{% url 'goods:list' goods_type.id page.next_page_number %}">下一页></a>
{% endif %}
</div>
DJANGO-天天生鲜项目从0到1-008-列表页的更多相关文章
- django天天生鲜项目
.后台admin管理天天生鲜商品信息 models里 from django.db import modelsfrom tinymce.models import HTMLField #需要pip安装 ...
- (生鲜项目)08. ModelSerializer 实现商品列表页, 使用Mixin来实现返回, 以及更加方便的ListAPIView, 以及分页的设置
第一步: 学会使用ModelSerializer, 并且会使用ModelSerializer相互嵌套功能 1. goods.serializers.py from rest_framework imp ...
- DJANGO-天天生鲜项目从0到1-007-首页静态化与缓存
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- python 天天生鲜项目
python 天天生鲜项目 django版:https://github.com/Ivy-1996/fresh flask版:https://github.com/Ivy-1996/flask-fre ...
- Django之天天生鲜项目
准备工作 1.配置settings.py内置文件 注意: AUTH_USER_MODEL配置参数要在第一次迁移数据库之前配置,否则可能django的认证系统工作不正常 2.创建应用 3.配置主路由 一 ...
- DJANGO-天天生鲜项目从0到1-012-订单-用户订单页面
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- DJANGO-天天生鲜项目从0到1-011-订单-订单提交和创建
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- DJANGO-天天生鲜项目从0到1-010-购物车-购物车操作页面(勾选+删改)
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- DJANGO-天天生鲜项目从0到1-009-购物车-Ajax实现添加至购物车功能
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
- DJANGO-天天生鲜项目从0到1-009-搜索功能实现(django-haystack+whoosh+jieba)
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...
随机推荐
- 2、尚硅谷_SSM高级整合_创建Maven项目.avi
第一步我们新建立一个web工程 这里首先要勾选上enable的第一个复选框 这里要勾选上add maven support 我们在pom.xml中添加sevlet的依赖 创建java web项目之后, ...
- springboot使用多个@RestControllerAdvice时的拦截顺序
我们的项目中经常会使用到别人的模块,例如我的项目demo,要依赖别人的A模块,以及基础的核心core模块,此时core模块有一个使用了@RestControllerAdvice的类,负责拦截所有的co ...
- 近期Java高级开发岗面试总结
原文出处:公众号:编程大道 作者:walking 近期Java高级开发岗面试总结 哈喽大家好,我是walking,这是我的公众号:编程大道. 很久没和大家见面了,文章更新的速度略有延后.这个公众号断断 ...
- JavaScript基础数组的字面声名法(010)
1.两种方法的对比 数组在JavaScript中,就像大多数的其它语言 一样,是对象.我们可以使用JavaScript内置的数组构造函数Array()来创建数组.就象对象的字面声名法一样,数组也可以采 ...
- 运行python出现 SyntaxError: Non-ASCII character '\xe6' in file /Users/finup/Documents/python_project/test.py 解决办法
使用pycharm运行程序时出现以下错误 这个错误主要是由于python2的编码默认是ASCII,你的文件里有中文就必须要用utf-8编码,只要在文件需要在文件开头标注 #coding=utf-8如下 ...
- 个人对于flask中蓝图的理解
什么是蓝图? 蓝图可以理解为,是一种对项目中的代码进行模块化管理的工具,相当于python中的包为什么要使用蓝图? 在一个py文件中具有多个功能代码,不利于维护和管理. 如果在其他的模块中去调用视图函 ...
- HTTPS连接建立过程(单向&双向)
HTTPS连接建立过程(单向&双向) 什么是https SSL(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Securit ...
- 烦人的B数
B树:二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点: B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点: 所有关键字在整颗树中出现, ...
- [PA2015]Siano 单调栈
由于某人找了个单调栈的题解但是没研究透所以让我们来研究............ 首先先来考虑下面一种情况,假设第\(k\)次切割时,天数为\(d_k\),高度为\(b_k\),第\(k+1\)次切割时 ...
- BUUCTF-Misc-No.2
比赛信息 比赛地址:Buuctf靶场 [GUET-CTF2019]虚假的压缩包 | SOLVED 解压文件夹,发现2个zip,第一个伪加密,破解后 n=33 e=3 m=0 while m<10 ...