Django入门与实践-第23章:分页实现(完结)
- #从现在起,我们将在 board_topics 这个视图中来操作。
- python manage.py shell
- from django.contrib.auth.models import User
- from boards.models import Board, Topic, Post
- user = User.objects.first()
- board = Board.objects.get(name='Django')
- for i in range(100):
- subject = 'Topic test #{}'.format(i)
- topic = Topic.objects.create(subject=subject, board=board, starter=user)
- Post.objects.create(message='Lorem ipsum...', topic=topic, created_by=user)
- #在我们返回去写代码之前,让我们用 python shell 来做一些更多的实验:
- python manage.py shell
- from boards.models import Topic
- Topic.objects.count()
- Topic.objects.filter(board__name='Django').count()
- queryset = Topic.objects.filter(board__name='Django').order_by('-last_updated')
- #定义一个你要分页的查询集(QuerySet)的排序是很重要的。否则,会返回给你错误的结果。
- #现在让我们导入 Paginator 工具:
- from django.core.paginator import Paginator
- paginator = Paginator(queryset, 20)
- #这里我们告诉Django将查询集按照每页20个元素分页。
- paginator.count
- paginator.num_pages
- paginator.page_range
- paginator.page(2)
- page = paginator.page(2)
- type(page)
- type(paginator)
- #我们来简单看一下 Page 类提供的属性和方法:
- page = paginator.page(1)
- page.has_next()
- page.has_previous()
- page.has_other_pages()
- page.next_page_number()
- #这里是我们如何使用 FBV 来实现分页:
- #boards/views.py
- from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
- def board_topics(request, pk):
- board = get_object_or_404(Board, pk=pk)
- queryset = board.topics.order_by('-last_updated').annotate(replies=Count('posts') - 1)
- page = request.GET.get('page', 1)
- paginator = Paginator(queryset, 20)
- try:
- topics = paginator.page(page)
- except PageNotAnInteger:
- topics = paginator.page(1)
- except EmptyPage:
- topics = paginator.page(paginator.num_pages)
- return render(request, 'topics.html', {'board': board, 'topics': topics})
- 在 topics HTML列表的基础上,我们可以渲染分页组件:
- <!--templates/topics.html-->
- {% if topics.has_other_pages %}
- <nav aria-label="Topics pagination" class="mb-4">
- <ul class="pagination">
- {% if topics.has_previous %}
- <li class="page-item">
- <a class="page-link" href="?page={{ topics.previous_page_number }}">Previous</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Previous</span>
- </li>
- {% endif %}
- {% for page_num in topics.paginator.page_range %}
- {% if topics.number == page_num %}
- <li class="page-item active">
- <span class="page-link">
- {{ page_num }}
- <span class="sr-only">(current)</span>
- </span>
- </li>
- {% else %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
- </li>
- {% endif %}
- {% endfor %}
- {% if topics.has_next %}
- <li class="page-item">
- <a class="page-link" href="?page={{ topics.next_page_number }}">Next</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Next</span>
- </li>
- {% endif %}
- </ul>
- </nav>
- {% endif %}
- #GCBV 分页
- #下面,相同的实现,但这次使用ListView。
- #boards/views.py
- class TopicListView(ListView):
- model = Topic
- context_object_name = 'topics'
- template_name = 'topics.html'
- paginate_by = 20
- def get_context_data(self, **kwargs):
- kwargs['board'] = self.board
- return super().get_context_data(**kwargs)
- def get_queryset(self):
- self.board = get_object_or_404(Board, pk=self.kwargs.get('pk'))
- queryset = self.board.topics.order_by('-last_updated').annotate(replies=Count('posts') - 1)
- return queryset
- #myproject/urls.py
- url(r'^boards/(?P<pk>\d+)/$', views.TopicListView.as_view(), name='board_topics'),
- #templates/topics.html
- {% block content %}
- <div class="mb-4">
- <a href="{% url 'new_topic' board.pk %}" class="btn btn-primary">New topic</a>
- </div>
- <table class="table mb-4">
- <!-- table content suppressed -->
- </table>
- {% if is_paginated %}
- <nav aria-label="Topics pagination" class="mb-4">
- <ul class="pagination">
- {% if page_obj.has_previous %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Previous</span>
- </li>
- {% endif %}
- {% for page_num in paginator.page_range %}
- {% if page_obj.number == page_num %}
- <li class="page-item active">
- <span class="page-link">
- {{ page_num }}
- <span class="sr-only">(current)</span>
- </span>
- </li>
- {% else %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
- </li>
- {% endif %}
- {% endfor %}
- {% if page_obj.has_next %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Next</span>
- </li>
- {% endif %}
- </ul>
- </nav>
- {% endif %}
- {% endblock %}
- #可复用的分页模板
- #就像我们在 form.html 中封装模板时做的一样,我们也可以为分页的HTML代码片创建类似的东西。
- #我们来对主题帖子页面进行分页,进而找到一种复用分页组件的方法法。
- #boards/views.py
- class PostListView(ListView):
- model = Post
- context_object_name = 'posts'
- template_name = 'topic_posts.html'
- paginate_by = 2
- def get_context_data(self, **kwargs):
- self.topic.views += 1
- self.topic.save()
- kwargs['topic'] = self.topic
- return super().get_context_data(**kwargs)
- def get_queryset(self):
- self.topic = get_object_or_404(Topic, board__pk=self.
- kwargs.get('pk'), pk=self.kwargs.get('topic_pk'))
- queryset = self.topic.posts.order_by('created_at')
- return queryset
- #更新一下 url.py
- url(r'^boards/(?P<pk>\d+)/topics/(?P<topic_pk>\d+)/$', views.PostListView.as_view(), name='topic_posts'),
- 现在,我们从topics.html模板中获取分页部分的html代码片,
- 并在templates/includes 文件夹下面创建一个名为 pagination.html 的新文件,
- 和 forms.html 同级目录:
- #templates/includes/pagination.html
- {% if is_paginated %}
- <nav aria-label="Topics pagination" class="mb-4">
- <ul class="pagination">
- {% if page_obj.has_previous %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_obj.previous_page_number }}">Previous</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Previous</span>
- </li>
- {% endif %}
- {% for page_num in paginator.page_range %}
- {% if page_obj.number == page_num %}
- <li class="page-item active">
- <span class="page-link">
- {{ page_num }}
- <span class="sr-only">(current)</span>
- </span>
- </li>
- {% else %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_num }}">{{ page_num }}</a>
- </li>
- {% endif %}
- {% endfor %}
- {% if page_obj.has_next %}
- <li class="page-item">
- <a class="page-link" href="?page={{ page_obj.next_page_number }}">Next</a>
- </li>
- {% else %}
- <li class="page-item disabled">
- <span class="page-link">Next</span>
- </li>
- {% endif %}
- </ul>
- </nav>
- {% endif %}
- #现在,我们在 topic_posts.html 文件中来使用它:
- #templates/topic_posts.html
- {% block content %}
- <div class="mb-4">
- <a href="{% url 'reply_topic' topic.board.pk topic.pk %}"class="btn btn-primary" role="button">Reply</a>
- </div>
- {% for post in posts %}
- <div class="card {% if forloop.last %}mb-4{% else %}mb-2{% endif %} {% if forloop.first %}border-dark{% endif %}">
- {% if forloop.first %}
- <div class="card-header text-white bg-dark py-2 px-3">{{ topic.subject }}</div>
- {% endif %}
- <div class="card-body p-3">
- <div class="row">
- <div class="col-2">
- <img src="{% static 'img/avatar.svg' %}" alt="{{post.created_by.username }}" class="w-100">
- <small>Posts: {{ post.created_by.posts.count }}</small>
- </div>
- <div class="col-10">
- <div class="row mb-3">
- <div class="col-6">
- <strong class="text-muted">{{ post.created_by.username }}</strong>
- </div>
- <div class="col-6 text-right">
- <small class="text-muted">{{ post.created_at}}</small>
- </div>
- </div>
- {{ post.message }}
- {% if post.created_by == user %}
- <div class="mt-3">
- <a href="{% url 'edit_post' post.topic.board.pk post.topic.pk post.pk %} "class="btn btn-primary btn-sm" role="button">Edit</a>
- </div>
- {% endif %}
- </div>
- </div>
- </div>
- </div>
- {% endfor %}
- {% include 'includes/pagination.html' %}
- {% endblock %}
- 我们同样也可以更新一下先前的模板,topics.html 模板同样也可以这个封装的分页模板。
- #templates/topics.html
- {% block content %}
- <div class="mb-4">
- <a href="{% url 'new_topic' board.pk %}" class="btn btn-primary">New topic</a>
- </div>
- <table class="table mb-4">
- <!-- table code suppressed -->
- </table>
- {% include 'includes/pagination.html' %}
- {% endblock %}
Django入门与实践-第23章:分页实现(完结)的更多相关文章
- Django入门与实践-第15章:用户注销(完结)
# myproject/settings.py LOGOUT_REDIRECT_URL = 'home' http://127.0.0.1:8000/logout/ # myproject/urls. ...
- Django入门与实践-第26章:个性化工具(完结)
http://127.0.0.1:8000/boards/1/topics/62/reply/ 我觉得只添加内置的个性化(humanize)包就会很不错. 它包含一组为数据添加“人性化(human t ...
- Django入门与实践-第14章:用户注册(完结)
http://127.0.0.1:8000/signup/ django-admin startapp accounts INSTALLED_APPS = [ 'accounts', ] # mypr ...
- Django入门与实践-第13章:表单处理(完结)
http://127.0.0.1:8000/boards/1/ http://127.0.0.1:8000/boards/2/ http://127.0.0.1:8000/boards/3/ http ...
- Django入门与实践-第12章:复用模板(完结)
http://127.0.0.1:8000/http://127.0.0.1:8000/boards/1/http://127.0.0.1:8000/boards/2/http://127.0.0.1 ...
- Django入门与实践-第11章:URL 分发(完结)
http://127.0.0.1:8000http://127.0.0.1:8000/boards/1/http://127.0.0.1:8000/boards/2/http://127.0.0.1: ...
- Django入门与实践-第25章:Markdown 支持(完结)
http://127.0.0.1:8000/boards/1/topics/102/reply/ 让我们在文本区域添加 Markdown 支持来改善用户体验. 你会看到要实现这个功能非常简单. 首先, ...
- Django入门与实践-第24章:我的账户视图(完结)
http://127.0.0.1:8000/settings/account/ #好的,那么,这部分将是我们最后的一个视图.之后,我们将专心来改进现有功能. #accounts/views.py fr ...
- Django入门与实践-第22章:基于类的视图
http://127.0.0.1:8000/boards/1/topics/2/posts/2/edit/ http://127.0.0.1:8000/ #boards/views.py from d ...
随机推荐
- html页面中iframe导致JavaScript失效
<body onload=“reset()”> <div id="part1"> some thing here .... <div> < ...
- Java LinkedList的实现原理
LinkedList是Java List类型的集合类的一种实现,此外,LinkedList还实现了Deque接口.本文基于Java1.8,对于LinkedList的实现原理做一下详细讲解. (Java ...
- Rust语言学习笔记(4)
Variables and Mutability(变量和可变性) 变量声明有三种:不变量(运行期的常量),变量以及(编译期的)常量. 变量可以重复绑定,后声明的变量覆盖前面声明的同名变量,重复绑定时可 ...
- delphi实现映射和断开网络驱动器
type TNetDiskMapper=class private FNetResource: TNetResource; FUserName,FPassWord:PWideChar; public ...
- java-- 的子类/父类构造方法 转
前提:父类和子类同时都有有参的构造函数和无参构造函数. Java中的子类初始化时初值为空.调用顺序为先调用父类无参构造函数,然后调用子类无参构造函数. java中的子类初始化时初值不为空.调用顺序为先 ...
- C语言实现大数四则运算
一.简介 众所周知,C语言中INT类型是有限制,不能进行超过其范围的运算,而如果采用float类型进行运算,由于float在内存中特殊的存储形式,又失去了计算的进度.要解决整个问题,一种解决方法是通过 ...
- 日志记录发布网站之后不成功,对路径“C:\Inetpub\wwwroot\***\***.xls”的访问被拒绝。
主要是web程序的根目录文件夹路径访问权限不够,新增加一个everyone的完全控制读写的权限即可!---------折磨了两天,才发现使劲使错了地方. 另外: 一定谨记!!!!! 所写的路径如果不存 ...
- 基于MSAA的QQ界面信息获取的实现
主要技术(Microsoft Active Accessibility)讲解: 以下是微软对于此技术的说明 Microsoft Active Accessibility Version 2.0 Pur ...
- python之面向对象之反射运用
先看下hasattr和getattr在反射中的用法 import sys class apache(object): def __init__(self,tcp): self.tcp = tcp de ...
- 一个性能较好的JVM参数配置
一个性能较好的web服务器jvm参数配置: -server//服务器模式-Xmx2g //JVM最大允许分配的堆内存,按需分配-Xms2g //JVM初始分配的堆内存,一般和Xmx配置成一样以避免每次 ...