技术交流QQ群:1027579432,欢迎你的加入!
本教程来源于B站杨仕航Django2.0开发视频教程,如需转载,必须注明来源!
1.为什么先讲分页功能
先讲分页功能,新增或编辑博客内容在admin后台操作.png
2.快速添加新的博客
shell命令行模式下添加新博客:
python manage.py shell,如下图所示:
进入shell命令行模式.png
for循环执行新增博客代码
添加一篇新的博客,涉及到Blog这个模型。因此在shell命令行模式下导入Blog这个模型。再用dir()方法来查看模型是否成功导入。如下图所示:
导入Blog博客模型.png
查询现有博客情况,如下图中的方法:
查询现有博客信息.png
3.模型新增对象
新增博客后的网页.png
>>> from blog.models import Blog
>>>
>>>
>>>
>>> Blog.objects.all()
>, >,
介>>]
>>> Blog.objects.all().count()
3
>>> blog = Blog()
>>> Blog.objects.all()
>, >,
介>>]>
>>> blog.title = "shell模式下的第一篇博客"
>>> blog.content = "这是一篇测试博客,233333333333333333333333333333333"
>>> from blog.models import BlogType
>>> dir()
['Blog', 'BlogType', '__builtins__', 'blog']
>>> BlogType.objects.all()
, , ]>
>>> blog_type = BlogType.objects.all()[1]
>>> blog.blog_type = blog_type
>>> from django.contrib.auth.models import User
>>> User.objects.all()
]>
>>> User.objects.all()
]>
>>> user = User.objects.all()[0]
>>> blog.author = user
>>> blog.save()
>>> Blog.objects.all()
>, >,
介>>, >]>
>>> Blog.objects.all().count()
4
>>> dir(blog)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_check_column_name_clashes', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_model_name_db_lookup_clashes', '_check_ordering', '_check_swappable', '_check_unique_together', '_do_insert', '_do_update', '_get_FIELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_save_parents', '_save_table', '_set_pk_val', '_state', 'author', 'author_id', 'blog_type', 'blog_type_id', 'check', 'clean', 'clean_fields', 'content', 'created_time', 'date_error_message', 'delete', 'from_db', 'full_clean', 'get_deferred_fields', 'get_next_by_created_time', 'get_next_by_last_updated_time', 'get_previous_by_created_time', 'get_previous_by_last_updated_time', 'id', 'last_updated_time', 'objects', 'pk', 'prepare_database_save', 'refresh_from_db', 'save', 'save_base', 'serializable_value', 'title', 'unique_error_message', 'validate_unique']
>>> blog.last_updated_time
datetime.datetime(2020, 5, 13, 13, 44, 45, 113603, tzinfo=)
shell命令行模式下,快速添加大批量博客。具体效果如下如所示:
>>> for i in range(1,31):
... blog = Blog()
... blog.title = "for %s" % i
... blog.content = "这是for循环生成的第%s篇博客" % i
... blog.blog_type = blog_type
... blog.author = user
... blog.save()
...
...
>>> Blog.objects.all().count()
34
shell命令行模式下,快速添加大批量博客.png
4.分页器实现分页
通过上图我们可以看出,当一下显示所有的博客时。因此实现分页功能,更便于我们查看想要浏览的博客。
>>> del Blog # 删除某个模型
>>> Blog
Traceback (most recent call last):
File "", line 1, in
NameError: name 'Blog' is not defined
>>> exit()
>>> python manage.py shell
>>> dir()
['__builtins__']
>>> from django.core.paginator import Paginator
>>> from blog.models import Blog
>>> Blog.objects.all()
>, >,
介>>, >, >,
>, >, >, >, >, >, >, >, >, >, >, >, >, >, >, '...(remaining elements truncated)...']>
>>> blogs = Blog.objects.all()
>>> blogs.count()
34
>>> paginator = Paginator(blogs, 10)
:1: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: QuerySet.
出现上面的UnorderedObjectListWarning错误,这是由于没有设置分页后每一页按照什么顺序排序。因此打开blog目录下的models.py文件,在Blog类下添加Meta类如下所示:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
# 创建博文类型模型
class BlogType(models.Model):
type_name = models.CharField(max_length=15)
def __str__(self):
return self.type_name
# 创建博文模型
class Blog(models.Model):
title = models.CharField(max_length=50)
# 一篇博文属于一种类型,因此博客通过外键关联到博文类型
blog_type = models.ForeignKey(BlogType, on_delete=models.DO_NOTHING)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
created_time = models.DateTimeField(auto_now_add=True)
last_updated_time = models.DateTimeField(auto_now=True)
def __str__(self):
return "" % self.title
class Meta:
ordering = ['-created_time']
由于已经修改了Blog模型,所以要进行同步数据库。输入如下命令,如下图所示:
E:\Django\mysite_env\Scripts\mysite
$ python manage.py makemigrations
Migrations for 'blog':
blog\migrations\0003_auto_20200513_2224.py
- Change Meta options on blog
E:\Django\mysite_env\Scripts\mysite
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying blog.0003_auto_20200513_2224... OK
E:\Django\mysite_env\Scripts\mysite
$ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
May 13, 2020 - 22:24:47
Django version 2.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
退出之前的shell命令行模型,重新进入shell命令行模式下,输入如下代码:
>>> from django.core.paginator import Paginator
>>> from blog.models import Blog
>>> blogs = Blog.objects.all()
>>> paginator = Paginator(blogs, 10)
>>> paginator
>>> dir(paginator)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_check_object_list_is_ordered', '_get_page', 'allow_empty_first_page', 'count', 'get_page', 'num_pages', 'object_list', 'orphans', 'page', 'page_range', 'per_page', 'validate_number']
>>> paginator.__doc__
>>> paginator.count
34
>>> paginator.num_pages
4
>>> paginator.page_range
range(1, 5)
>>>
>>> page1 = paginator.page(1)
>>> page1
>>> dir(page1)
['__abstractmethods__', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_abc_cache', '_abc_negative_cache', '_abc_negative_cache_version', '_abc_registry', 'count', 'end_index', 'has_next', 'has_other_pages', 'has_previous', 'index', 'next_page_number', 'number', 'object_list', 'paginator', 'previous_page_number', 'start_index']
>>> page1.count
>
>>> help(page1.count)
Help on method count in module collections.abc:
count(value) method of django.core.paginator.Page instance
S.count(value) -> integer -- return number of occurrences of value
>>>
>>> page1.object_list
[>, >, >, >, >, >, >, >, >, >]
>>> page1.object_list.count
分页器实现分页.png
5.分页的使用
前端页面:向后端服务器发送请求,请求打开具体的分页内容;
后端服务器:处理请求,返回具体分页内容响应请求;
例如,可以通过在浏览器中输入localhost:8000/blog/?page=1来访问第一页中的所有方法。因为前端通过url向服务器发送了GET请求,所以打开blog文件目录下的views.py文件,在blog_list()和blogs_with_type()函数中增加该请求对应的方法。views.py文件的内容如下:
from django.shortcuts import render_to_response, get_object_or_404
from django.core.paginator import Paginator
from .models import Blog, BlogType
# Create your views here.
def blog_list(request):
blogs_all_list = Blog.objects.all()
paginator = Paginator(blogs_all_list, 10) # 每10篇进行一次分页
page_num = request.GET.get('page', 1) # 获取url的页码参数(GET请求)
page_of_blogs = paginator.get_page(page_num)
context = {}
context['blogs'] = page_of_blogs.object_list
context['page_of_blogs'] = page_of_blogs
context['blog_types'] = BlogType.objects.all()
return render_to_response('blog/blog_list.html', context)
def blog_detail(request, blog_pk):
context = {}
context['blog'] = get_object_or_404(Blog, pk=blog_pk)
return render_to_response('blog/blog_detail.html', context)
def blogs_with_type(request, blog_type_pk):
blogs_all_list = Blog.objects.all()
paginator = Paginator(blogs_all_list, 2) # 每2篇进行一次分页
page_num = request.GET.get('page', 1) # 获取url的页码参数(GET请求)
page_of_blogs = paginator.get_page(page_num)
context = {}
blog_type = get_object_or_404(BlogType, pk=blog_type_pk)
context['blog_type'] = blog_type
context['blogs'] = Blog.objects.filter(blog_type=blog_type)
context['blog_types'] = BlogType.objects.all()
context['page_of_blogs'] = page_of_blogs
return render_to_response('blog/blogs_with_type.html', context)
接着,修改blog文件目录下的templates文件夹下的blog_list.html模板文件,经过views.py处理请求后,返回新的结果给前端页面。blog_list.html修改后的结果如下所示:
{% extends 'base.html' %}
{# blog_list.html文件内容 #}
{# 页面标题 #}
{% block title %}我的网站{% endblock %}
{% block nav_blog_active %}active{% endblock %}
{% load staticfiles %}
{% block header_extends %}
{% endblock %}
{# 页面内容 #}
{% block content %}
{% block blog_list_title %}博客列表(一共有{{ page_of_blogs.paginator.count }}篇博客){% endblock %}
{% for blog in blogs %}
{{ blog.title }}
{{ blog.blog_type }}    
{{ blog.created_time|date:"Y-m-d" }}
{{ blog.content|truncatechars:120 }}
{% empty %}
暂无博客,敬请期待
{% endfor %}
{# 上一页 #}
{% if page_of_blogs.has_previous %}
«
{% else %}
«
{% endif %}
{# 全部页码 #}
{% for page_num in page_of_blogs.paginator.page_range %}
{{ page_num }}{% endfor %}
{# 下一页 #}
{% if page_of_blogs.has_next %}
»
{% else %}
»
{% endif %}
博客分类
{% endblock %}
添加分页按钮后的前端页面.png