Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件

本人另外有一篇文档是专门更新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>

但是这个方法的可扩展性不是很好,比如我们要追加一个排序条件时,就需要修改前端的超链接,如:


<a href="?keywords={{keywords}}&orderby={{orderby}}&page_num={{ goods.next_page_number }}">下一页a>

而且在没有筛选条件时,浏览器的超链接会多显示出一个筛选条件,如:
Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件_第1张图片

这里向大家提供了一个优雅地保存筛选条件的方法。可以不用修改前端翻页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
没有多余的筛选条件
Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件_第2张图片
2.在查找商品名中含有“1”的商品时:
在第一页只有搜索关键词,翻页后则追加了一个页面编码
Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件_第3张图片
翻页后:
Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件_第4张图片3.多个筛选条件(追加排序)
可以看到,对搜索商品名中含有“1”的商品列表按照价格降序后的url地址为http://localhost:8002/allgoods?keywords=1&orderby=-price
下一页的url预览为http://localhost:8002/allgoods?keywords=1&orderby=-price&page_num=2
Django 实现搜索结果分页(筛选结果分页),以及优雅添加多个筛选条件_第5张图片

你可能感兴趣的:(Django,笔记,python,django,python,前端)