dbms定义视图为什么不能用order by_(十)Django视图补充快速建立翻页

二十一、Django视图补充

    1.ListView,快速实现数据列表页。数据库里面填充了100条数据,示例代码如下:

from django.views.generic import ListViewclass ListTest(ListView):    # 引用的模型名称    model = Article    # 引用的模板    template_name = 'Article-Test.html'    # 一页多少条数据    paginate_by = 10    # 上下文名称,即模板中调用的变量    context_object_name = 'my_articles'    # 排序规则    ordering = '-pk'    # 翻页参数    page_kwarg = 'p'

4aad14c874964ba3f0146ef1d4ae2fe0.png

ListView类会调用get_context_data方法,所以如果我们还想传递上下文,可以在此方法中先获取父类的context,再增加自己想要的内容(这是因为如果不先调用父类,那么很多参数我们就用不了);get_queryset会默认使用all()返回所有的queryset,我们也可以进行修改,过滤掉自己不想要的数据,但是我在测试这个方法的时候,命令行提示Pagination may yield inconsistent results with an unordered object_list,我就很奇怪,明明上面定义了ordering,怎么会没有排序呢?

def get_context_data(self, **kwargs):        context = super().get_context_data(**kwargs)        context["user_name"] = 'fire'        print("*"*30)        for i,v in context.items():            print(str(i) + ': '+str(v))        print("*"*30)        return contextdef get_queryset(self):  # return super().get_queryset()  return Article.objects.filter(pk__lte=95)

我看了下源码,如下,确实是获取到了排序规则的

ordering = self.get_ordering() # -pkif ordering:  if isinstance(ordering, str): # yes      ordering = (ordering,)    queryset = queryset.order_by(*ordering)return queryset

再仔细看了下自己写的代码,悟了,里面唯一的区别在于我没有继承django自身get_queryset的方法,换一种写法就可以了

return super().get_queryset().filter(pk__lte =10)

super().get_queryset()是一个queryset对象,或者不想继承django自身的方法,自己在Article.objects.filter(pk__lte=95)后面跟上排序的order规则也可以。

    在ListView的get_context_data方法中,context对象中的paginator和page_obj会经常使用,二者的导出路径均在django.core.paginator下,paginator对应的类是Paginator,常用方法num_pages,取得总页数,page_range取得页数范围值,count取得总条数,需要注意的是,该项针对的是你在get_queryset中所筛选出的数据,例如,当你设置了pk__lte =10,那么count只会取得pk__lte =10满足的数据条目!其中page_obj对应的是Page类,主要有has_next,has_previous,previous_page_number,number(当前页),next_page_number,start_index(获取当页第一条数据下标,即在总列表中第几条索引),end_index。

    来看一个利用Bootstrap和ListView快速实现普通分类页的小视频。

    其中模板页面利用paginator和page_obj的一些属性,判断链接跳转,以及是否存在第一页/最后一页以禁止点击。源代码如下:

# Article-List.html<ul>{% for article in my_arts %}<li>{{article.title}}li>{% endfor %}ul><ul class="pagination">{# 上一页 #}{% if not page_obj.has_previous %}<li class='disabled'><a href="javascript:void(0)" >上一页a>li>{% else %}# 两种写法任选其一{% comment %} <li><a href="?p={{page_obj.previous_page_number}}" >上一页a>li> {% endcomment %}<li><a href="{% url 'front:index' %}?p={{page_obj.previous_page_number}}">上一页a>li>{% endif %}{# 中间页 #}{% for index in paginator.page_range %}{% if index == page_obj.number %}<li class='active'>{% else %}<li>{% endif %}<a href="?p={{index}}">{{index}}a>li>{% endfor %}{# 下一页 #}{% if not page_obj.has_next %}<li class='disabled'><a href="javascript:void(0)" >下一页a>li>{% else %}<li><a href="?p={{page_obj.next_page_number}}" >下一页a>li>{% endif %}ul>

但是这个翻页有一个问题,就是展示了所有的分页,一旦数据有成千上万条,那翻页的摆放就懵逼了,所以我们可以再更新一下翻页的代码,如下:

可以看到,前端页面仅显示了当前选中页面的左右两边各三页的链接,前后各增加第一页和最后一页的链接,中间全部用省略号代替,前端html页面和后端视图代码如下:

# articles.html{# 上一页 #}{% if not page_obj.has_previous %}    <li class='disabled'><a href="javascript:void(0)">上一页a>li>{% else %}    <li><a href="{% url 'front:index' %}?p={{page_obj.previous_page_number}}">上一页a>li>{% endif %}{# 中间的页数处理#}{% if left_has_more %}    <li><a href="{% url 'front:index' %}?p=1">1a>li>    <li><a href="javascript:void(0)">...a>li>{% endif %}{% for left_page in left_pages %}    <li><a href="{% url 'front:index' %}?p={{left_page}}">{{left_page}}a>li>{% endfor %}    {# 当前页#}<li class='active'><a href="javascript:void(0)">{{current_page}}a>li>{% for right_page in right_pages %}    <li><a href="{% url 'front:index' %}?p={{right_page}}">{{right_page}}a>li>{% endfor %}{% if right_has_more %}    <li><a href="javascript:void(0)">...a>li>    <li><a href="{% url 'front:index' %}?p={{num_pages}}">{{num_pages}}a>li>{% endif %}{# 下一页 #}{% if not page_obj.has_next %}    <li class='disabled'><a href="javascript:void(0)">下一页a>li>{% else %}    <li><a href="{% url 'front:index' %}?p={{page_obj.next_page_number}}">下一页a>li>{% endif %}

视图层:

class ListClass(ListView):    template_name = 'articles.html'    model= Article    page_kwarg = 'p'    paginate_by = 10    ordering = 'pk'    context_object_name = "my_articles"    def get_context_data(self, **kwargs):        context = super().get_context_data(**kwargs)        res = self.getPaginationInfo(context['paginator'], context['page_obj'])        context.update(res)        return context    def getPaginationInfo(self, paginator, page_obj, around_page=3):        current_page = page_obj.number        left_has_more = False        right_has_more = False        if current_page - around_page > 1:            left_pages = range(current_page - around_page, current_page)            left_has_more = True        else:            left_pages = range(1, current_page)        if current_page + 1 + around_page > paginator.num_pages:            right_pages = range(current_page + 1, paginator.num_pages + 1)        else:            right_pages = range(current_page + 1, current_page + around_page + 1)            right_has_more = True        return {            'left_pages': left_pages,            'right_pages': right_pages,            'current_page':current_page,            'left_has_more':left_has_more,            'right_has_more':right_has_more,            'num_pages':paginator.num_pages        }

实现原理也很简单,就是利用paginator和page_obj的一些属性,函数,通过getPaginationInfo新增的around_page参数进行比较,只要当前页比around_page大1,那么说明左边肯定至少有around_page+1条数据,右边的处理也是同理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值