Django的类视图ListView用法(含详细分页paginate功能)

开发环境:

python 3.8.6 django 3.1.7

场景:

经常有从数据库中获取一批数据,然后在前端以列表的形式展现,比如:获取到所有的用户,然后在用户列表页面展示。

常规写法是,我们通过Django的ORM查询到所有的数据,然后展示出来,代码如下:

def user_list(request):
    """返回UserProfile中所有的用户"""
    users = UserProfile.objects.all()
    return render(request, 'talks/users_list.html', context={"user_list": users})

这样能够解决问题,但是Django针对这种常用场景,提供了一个更快速便捷的方式,那就是ListView,用法如下:

from django.views.generic import ListView
 
class UsersView(ListView):
    model = UserProfile
    template_name = 'talks/users_list.html'
    context_object_name = 'user_list'

如果需要对数据做过滤,ListView实现可以重写get_queryset函数方法实现,代码如下:

from django.views.generic import ListView
 
class UsersView(ListView):
    model = UserProfile
    template_name = 'talks/users_list.html'
    context_object_name = 'user_list'
 
       def get_queryset(self):
        """ 重写get_queryset()方法实现筛选排序,效果get_queryset()>queryset>model """
        sort = self.kwargs.get('sort')
        return Article.objects.all().order_by('-is_top', '-create_date')

如果想要返回给Template的数据需要多个,不仅仅是user_list,可能还有其他数据,如获取当前登陆用户的详细信息,就需要用到重写get_context_data方法,代码如下:

from django.views.generic import ListView
 
class UsersView(ListView):
    model = UserProfile
    template_name = 'talks/users_list.html'
    context_object_name = 'user_list'
 
    def get_context_data(self, **kwargs):   # 重写get_context_data方法
        # 很关键,必须把原方法的结果拿到
        context = super().get_context_data(**kwargs)
        username = self.request.GET.get('user', None)
        context['user'] = UserProfile.objects.get(username=username
        return context
 这样,你返回给Template页面时,get_context_data() 向template传递更多信息,模板可以直接用{{user}} 来调用。

接下来做前端页面的分页展示,完整步骤:

  • 应用views.py中用以下代码
from datetime import datetime

from django.shortcuts import render
from django.views.generic import ListView
from apps.blog import settings
from apps.blog.models import Article
from apps.blog.utils.blog import getPages


# blog首页列表
class blogIndexListView(ListView):
    """ 模板,标签名,分页:::template_name,context_object_name,paginate_by 都是固定名称不要更改 """
    template_name = 'blog/blog1.html'
    context_object_name = 'articles'
    paginate_by = getattr(settings, 'BASE_PAGE_BY', None)
    paginate_orphans = getattr(settings, 'BASE_ORPHANS', 0)
    http_method_names = ['GET', 'get']         # 加上这一行,告知允许那种请求方式

    # """ 排序 """
    # model = Article
    #
    # def get_ordering(self):
    #     sort = self.kwargs.get('sort')
    #     if sort == 'v':
    #         return '-views', '-update_date', '-id'
    #     return '-is_top', '-create_date'
    # """ 排序 """

    def get_queryset(self):
        """ 重写get_queryset()方法实现筛选排序,效果get_queryset()>queryset>model """
        sort = self.kwargs.get('sort')
        if sort == 'v':
            article = Article.objects.all().order_by('-views', '-update_date', '-id')
            return article
        return Article.objects.all().order_by('-is_top', '-create_date')

    def get_context_data(self, **kwargs):
        """ get_context_data() 向template传递更多信息,模板可以直接用{{now}} """
        context = super(blogIndexListView, self).get_context_data(**kwargs)
        context['now'] = datetime.now()
        paginator = context.get('paginator')
        page = context.get('page_obj')
        pages = getPages(paginator, page)
        context['pages'] = pages
        return context

paginate_by 是每页个数,可设置为具体值,我是写到settings中了。get_context_data为context上下文对象增加额外数据

  • 2. 创建utils.py文件,代码如下:
def getPages(paginator, page):
    """ 这部分是为了再有大量数据时,仍然保证所显示的页码数量不超过5 """
    if page.number < 3:
        if paginator.num_pages <= 5:
            pages = range(1, paginator.num_pages + 1)
        else:
            pages = range(1, 6)
    elif (page.number >= 3) and (page.number <= paginator.num_pages - 2):
        pages = range(page.number - 2, page.number + 3)
    else:
        pages = range(paginator.num_pages - 3, paginator.num_pages + 1)
    return pages
  • 3. 对应的模板文件blog.html中,代码如下:
<div class="pagination">
    <ul>
    {% if page_obj.has_previous %}
        <li>
            <a href="{% url 'blog:blog_home1' %}?page={{ page_obj.previous_page_number }}">上一页</a>
        </li>
    {% else %}
         <li class="disabled"><a href="#">上一页</a></li>
    {% endif %}
 <!--中间的页码,如果是当前页,添加active属性-->
    {% for page in pages %}
        {% if page == page_obj.number %}
         <li class="active">
             <a href="{% url 'blog:blog_home1' %}?page={{ page }}">{{ page }}</a>
        </li>
        {% else %}
            <li><a href="{% url 'blog:blog_home1' %}?page={{ page }}">{{ page }}</a></li>
        {% endif %}
    {% endfor %}
<!--#下一页-->
    {% if page_obj.has_next %}
        <li>
             <a href="{% url 'blog:blog_home1' %}?page={{ page_obj.next_page_number }}">下一页</a>
         </li>
    {% else %}
        <li class="disabled"><a href="x">下一页</a></li>
    {% endif %}
    </ul>
    <div class="sum-page">
        <ul>
            <li><span>共{{ page_obj.paginator.num_pages }}页</span></li>
        </ul>
    </div>

</div>

最后看下效果:

原文链接:http://www.itawp.com/286.html,转载请注明出处。

0

评论0

没有账号? 注册  忘记密码?