本人另外有一篇文档是专门更新Django的一些操作笔记,有需要可以收藏关注一下:Django笔记
分页器参考:Django高级之-分页器
场景:在对查询列表进行搜索、排序时,新手往往会遇到翻页后条件丢失的情况。一般的做法是将搜索条件传递到前端页面,然后将翻页链接写为:
<a href="?keywords={{keywords}}&page_num={{ goods.next_page_number }}">下一页</a>
# views.py
# 关键词查询
def allgoods(request):
goods = Goods.objects.all()
keywords = request.GET.get("keywords","")
if keywords:
goods = goods.filter(goodsName__icontains=keywords)
context={
"goods":goods,
"keywords":keywords,
}
return render(request, 'allgoods.html', context)
# allgoods.html
<form action="{% url 'allgoods' %}" method="get">
<input type="text" name="keywords" value="{{keywords}}">
<button type="submit">查询</button>
</form>
<table>
<tr>
<th>商品名</th>
<th>价格</th>
</tr>
{% for g in goods%}
<tr>
<td>{{g.goodsName}}</td>
<td>{{g.price}}</td>
</tr>
{% endfor %}
</table>
<ul>
<!-- 上一页 -->
{% if goods.has_previous %}
<a href="?keywords={{keywords}}&page_num={{ goods.previous_page_number }}">上一页</a>
{% endif %}
<!-- 根据页码跳转 -->
{% for p in page_range %}
{% if page_num == p %}
<a href="?keywords={{keywords}}&page_num={{p}}">{{p}}</a>
{% else %}
<a href="?keywords={{keywords}}&page_num={{p}}">{{p}}</a>
{% endif %}
{% endfor %}
<!-- 下一页 -->
{% if goods.has_next %}
<a href="?keywords={{keywords}}&page_num={{ goods.next_page_number }}">下一页</a>
{% endif %}
</ul>
但是这个方法的可扩展性不是很好,比如我们要追加一个排序条件时,就需要修改前端的超链接,如:
<!-- {{orderby}} == goodsName / -goodsName / price / -price -->
<a href="?keywords={{keywords}}&orderby={{orderby}}&page_num={{ goods.next_page_number }}">下一页</a>
而且在没有筛选条件时,浏览器的超链接会多显示出一个筛选条件,如:
这里向大家提供了一个优雅地保存筛选条件的方法。可以不用修改前端翻页url链接即可实现对多个筛选条件的追加
<a href="?{{mywhere|join:'&'}}&page_num={{ goods.next_page_number }}">下一页</a>
具体实现如下:
其中的关键操作是views.py
中的mywhere
列表和html
文件中的字符串拼接操作
# urls.py
urlpatterns=[
path("allgoods", views.allgoods, name="allgoods"), # 所有商品页面
]
# views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from testApp.models import Goods
def allgoods(request):
mywhere = []
# 获取商品列表
goods = Goods.objects.all()
# 关键词查询
keywords = request.GET.get("keywords","")
if keywords:
goods = goods.filter(goodsName__icontains=keywords)
mywhere.append("keywords="+keywords)
# 条件排序
orderby = request.GET.get("orderby","")
if orderby:
goods = goods.order_by(orderby)
mywhere.append("orderby="+orderby)
# 进行分页
paginator = Paginator(goods, 10) # 每页10条
page_num = request.GET.get('page_num',1) # 获取当前页数,没有则默认为1
try:
goods = paginator.page(page_num) # goods 为Page对象!
except PageNotAnInteger:
# If page is not an integer, deliver first page.
goods = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
goods = paginator.page(paginator.num_pages)
if paginator.num_pages > 11:
# 1、当前的页数小于6时,直接使用1到11区间的页面
if page_num-5 < 1:
page_range = range(1, 12)
# 2、当当前的页面数+5大于总页数的话,直接显示最后的11个数
elif page_num + 5 > paginator.num_pages:
page_range = range(paginator.num_pages - 11, paginator.num_pages + 1)
# 3、按照范围取值
else:
page_range = range(page_num - 5, page_num + 6)
else:
# 4、当前的页面有多少页显示多少页
page_range = paginator.page_range
# 最后一页
page_last = paginator.num_pages
context={
"goods": goods,
"page_range":page_range,
"page_last":page_last,
"mywhere": mywhere,
}
print("mywhere:",mywhere)
return render(request, "goodsList.html",context)
# goodsList.html
<form action="{% url 'allgoods' %}" method="get">
<input type="text" name="keywords" value="{{keywords}}">
<button type="submit">查询</button>
</form>
<a href="?{{mywhere|join:'&'}}&orderby=goodsName">商品名升序</a>
<a href="?{{mywhere|join:'&'}}&orderby=-goodsName">商品名降序</a>
<a href="?{{mywhere|join:'&'}}&orderby=price">价格升序</a>
<a href="?{{mywhere|join:'&'}}&orderby=-price">价格降序</a>
<table>
<tr>
<th>商品名</th>
<th>价格</th>
</tr>
{% for g in goods%}
<tr>
<td>{{g.goodsName}}</td>
<td>{{g.price}}</td>
</tr>
{% endfor %}
</table>
<ul class="pagination">
<!-- 上一页 -->
{% if goods.has_previous %}
<a href="?{{mywhere|join:'&'}}&page_num={{ goods.previous_page_number }}">上一页</a>
{% endif %}
<!-- 根据页码跳转 -->
{% for p in page_range %}
{% if page_num == p %}
<a href="?{{mywhere|join:'&'}}&page_num={{p}}">{{p}}</a>
{% else %}
<a href="?{{mywhere|join:'&'}}&page_num={{p}}">{{p}}</a>
{% endif %}
{% endfor %}
<!-- 下一页 -->
{% if goods.has_next %}
<a href="?{{mywhere|join:'&'}}&page_num={{ goods.next_page_number }}">下一页</a>
{% endif %}
</ul>
效果展示
1.首次进入列表页面时,可以看到顶部地址为localhost:8002/allgoods
最下方下一页地址预览为:localhost:8002/allgoods?&page_num=2
没有多余的筛选条件
2.在查找商品名中含有“1”的商品时:
在第一页只有搜索关键词,翻页后则追加了一个页面编码
翻页后:
3.多个筛选条件(追加排序)
可以看到,对搜索商品名中含有“1”的商品列表按照价格降序后的url地址为http://localhost:8002/allgoods?keywords=1&orderby=-price
下一页的url预览为http://localhost:8002/allgoods?keywords=1&orderby=-price&page_num=2