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

4 篇文章 0 订阅
2 篇文章 0 订阅

本人另外有一篇文档是专门更新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
翻页后:
图片43.多个筛选条件(追加排序)
可以看到,对搜索商品名中含有“1”的商品列表按照价格降序后的url地址为http://localhost:8002/allgoods?keywords=1&orderby=-price
下一页的url预览为http://localhost:8002/allgoods?keywords=1&orderby=-price&page_num=2
在这里插入图片描述

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
实现模糊查询和分页功能需要用到Django的ORM和Paginator模块。 模糊查询: 1. 在views.py中定义视图函数,接收用户输入的查询关键字,并使用icontains进行模糊匹配。 ```python from django.core.paginator import Paginator from django.shortcuts import render from .models import Book def book_search(request): keyword = request.GET.get('keyword') books = Book.objects.filter(name__icontains=keyword) return render(request, 'book_search.html', {'books': books}) ``` 2. 在模板中使用表单接收用户输入的关键字,展示查询结果。 ```html <form method="get" action="{% url 'book_search' %}"> <input type="text" name="keyword"> <button type="submit">搜索</button> </form> {% if books %} <ul> {% for book in books %} <li>{{ book.name }}</li> {% endfor %} </ul> {% else %} <p>暂无结果</p> {% endif %} ``` 分页: 1. 在views.py中定义视图函数,使用Paginator将查询结果分页。 ```python def book_list(request): books = Book.objects.all() paginator = Paginator(books, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'book_list.html', {'page_obj': page_obj}) ``` 2. 在模板中展示分页导航和当前页的数据。 ```html <ul> {% for book in page_obj %} <li>{{ book.name }}</li> {% endfor %} </ul> <div> {% if page_obj.has_previous %} <a href="?page={{ page_obj.previous_page_number }}">上一页</a> {% endif %} <span>{{ page_obj.number }}</span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">下一页</a> {% endif %} </div> ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值