模型使用流程

  • 配置数据库
  • 定义模型类
  • 激活模型
  • 使用模型

数据库配置

Django默认使⽤的是sqlite,但在⽣产环境中⼀般会⽤mysql、postgrsql、oracle 等关系型数据库。

在开发环境中,安装mysql的数据库驱动mysqlclient,mysqlclient是连接mysql的驱动,不能提供数据库服务,需要单独安装mysql。

1
pip install mysqlclient

在项⽬的 settings.py ⽂件中找到 DATABASES 配置项,将其信息修改为:

1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', #mysql数据库引擎
'NAME': 'test', #数据库名
'HOST':'localhost', #数据库服务器地址
'USER': 'test', #mysql数据库⽤户名
'PASSWORD': 'test123', #密码
'PORT':3306, #端⼝号,可选
}
}

ORM

对象关系映射(Oject Relational Mapping,简称ORM)模式是⼀种为了解决⾯向 对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使⽤描 述对象和数据库之间映射的元数据,⾃动⽣成sql语句,将程序中的对象⾃动保存 到关系数据库中。

优点:

  • 隐藏了数据库访问的细节,简化了sql的使⽤,提⾼了开发效率
  • 解耦业务逻辑层(view)和数据处理层(model),简化了开发流程,提⾼了 系统的可移植性
  • 提⾼了安全性

优点:

  • 执⾏效率低
  • 对复杂sql⽆能为⼒
  • 增加了学习成本

基本概念

⾯向对象概念 ⾯向关系概念
对象 记录(一行)
属性 字段(属性,列)
  • 一个模型类对应一个表
  • 每个模型都必须继承django.db.models.Model

模型属性

模型中的属性和数据库表的字段对应,必须定义。模型的属性需要定义成类属性

1
2
#属性定义语法为:
属性 = models.字段类型(选项)
  • 属性命名规则
    - 不能是python的保留关键字
    - 不允许使⽤连续的下划线,因为连续下划线在查询中会⽤到
    - 定义属性时需要指定字段类型
    - 主键⼀般不⽤⾃⼰定义,django会⾃动创建⾃增⻓主键列,如果你⾃⼰定 义了主键,则django不会再⾃动⽣成主键

字段类型

字段名称 字段说明 参数
AutoField ⼀个根据实际Id⾃动增⻓的 IntegerField(通常不指定 ⾃动 ⽣成) primary_key:bool 是否为主键
CharField 字符串,默认的表单样式是 TextInput max_length=字符⻓ 度
TextField ⼤⽂本字段,⼀般超过4000使 ⽤,默认的表单控件是 Textarea
IntegerField 整数
DecimalField 使⽤python的Decimal实例表 示的⼗进制浮点数
FloatField ⽤Python的float实例来表示的 浮点数
BooleanField true/false 字段,此字段的默认 表单控制是CheckboxInput
NullBooleanField ⽀持null、true、false三种值
DateField 使⽤Python的datetime.date实 例表示的⽇期,该字段默认对 应的表单控件是⼀个TextInput auto_now和 auto_now_add、 default这三个参数 不能同时共存
TimeField 使⽤Python的datetime.time实 例表示的时间 参数同DateField
DateTimeField 使⽤Python的 datetime.datetime实例表示的 ⽇期和时间 参数同DateField
ImageField 继承了FileField的所有属性和⽅ 法,但对上传的对象进⾏校 验,确保它是个有效的image
  • auto_now: 每次保存对象时,⾃动设置该字段为当前时间,⽤于”最后⼀次修 改”的时间戳,它总是使⽤当前⽇期,默认为false
  • auto_now_add: 当对象第⼀次被创建时⾃动设置当前时间,⽤于创建的时间 戳,它总是使⽤当前⽇期,默认为false

字段选项

适⽤于任何字段,可以实现字段的约束,在⽣成字段时通过⽅法的关键字参数指 定。

可选参数 说明
null 如果 True ,Django将 NULL 在数据库中存储空值。默认 是 False 。不要在字符串字段上使⽤。null是数据库范畴的概 念
blank 如果 True ,该字段允许为空。默认是 False 。同null不同, 如果字段有 blank=True ,则表单验证将允许输⼊空值。如果 字段有 blank=False ,则需要该字段。
db_column ⽤于此字段的数据库列的名称。如果没有给出,Django将使 ⽤该字段的名称。
db_index 如果 True ,将为此字段创建数据库常规索引。
unique 如果 True ,该字段在整个表格中必须是唯⼀的。
primary_key 如果 True ,此字段是模型的主键。
default 默认值 当前字段如果不给值则执⾏默认值

定义模型

我们可以在应⽤的models.py中定义模型:

1
2
3
4
5
6
from django.db import models
class 模型名(models.Model):
属性名 = models.字段名(字段选项/参数)
.....
class Meta: #可选,任何⾮字段的设置可以写到Meta中
db_table = 'user' #指定表名为uesr
  • 数据库的表名等于:应⽤名_模型名,如果想指定表名,可以在Meta中使⽤ db_table指定
  • 如果没有指定主键,Django将⾃动给表创建⼀个⾃增⻓主键,名为id
1
id = models.AutoField(primary_key=True)
  • Meta中常⽤设置:
名称 说明
db_table 数据库中的表名
abstract 当设置为True时,说明当前模型是抽象基类
managed 如果设置False,则迁移不会创建或删除表,默认是True
ordering ⽤于记录排序,ordering = [‘pub_date’]或降序ordering = [‘- pub_date’]

激活模型

  • 创建迁移⽂件 (此刻表并没有创建到库中)
1
$ python manage.py makemigrations
  • 执⾏迁移 (将模型创建到库中)
1
$ python manage.py migrate

然后在应⽤的migrations⽬录中应该⽣成了迁移⽂件

1
2
3
4
5
6
7
├── app
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py

注意:任何对字段或表的修改都需要重新迁移

  • 反向迁移 可以根据数据库中表⾃动创建模型
1
python manage.py inspectdb > App/models.py

模型的使用

我们可以在交互式Python shel环境中,使⽤Django提供的免费API。要调⽤ Python shell,请使⽤以下命令:

1
2
3
4
5
$ py -3 manage.py shell
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

增删改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def sql(request):
# 增
user = User(username='admin',password='123456')
user.save()

# 第二种增
data = {
'username': 'admin',
'password': '123456',
}
User.objects.create(**data)
# 改
user = User.objects.get(pk=1)
user.password = '654321'
user.save()

# 删
try:
user = User.objects.get(pk=1)
if user:
user.delete()
except Exception as error:
print(error)
return HttpResponse("操作完成")
  • 数据的逻辑删除

    对于重要数据,⼀般不会直接删除,会在表中增加⼀个字段⽐如: is_deleted,如果删除的话,将这个字段置为True,以后查询的时候不在查 询,这种操作称为逻辑删除

数据查询

过滤器查询

要从数据库检索数据,⾸先要获取⼀个查询集(QuerySet),查询集表示从数据库获
取的对象集合,它可以有零个,⼀个或多个过滤器。返回查询集的⽅法,称为过滤
器,过滤器根据给定的参数缩⼩查询结果范围,相当于sql语句中where或limit。

  • 在管理器上调⽤过滤器⽅法会返回查询集
  • 查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤
  • 惰性执行:创建查询集不会带来任何数据库的访问,直到调⽤数据时,才会访问数据库
  • 以下对查询集求值:迭代、切⽚、序列化、与if合⽤、 repr()/print()/len()/list()/bool()

遍历数据库所有数据:

1
2
3
def user_list(request):
users = User.objects.all()
return render(request,'list.html',locals())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<table border="1" width="200px">
<tr align="center">
<th>用户名</th>
<th>密码</th>
</tr>
{% for user in users %}
<tr align="center">
<td>{{ user.username }}</td>
<td>{{ user.password }}</td>
</tr>
{% endfor %}

</table>

</body>
</html>

过来取可串联使用,比如:users = User.objects.filter(username='Mxm7788', password='1').filter(id=5)

实现mysql limit功能显示前10条:User.objects.all()[:10]

实现mysql limit功能显示5-10条:User.objects.all()[4:11]

注意:Python切片包头不包尾

管理器的⽅法 返回类型 说明
模型类.objects.all() QuerySet 返回表中所有数据
模型类.objects.filter() QuerySet 返回符合条件的数据,相当于where
模型 类.objects.exclude() QuerySet 返回不符合条件的数据
模型 类.objects.order_by() QuerySet 对查询结果集进⾏排序
模型 类.objects.values() QuerySet 返回⼀个Queryset,其中每个对象为⼀个字典
模型 类.objects.values_list() QuerySet 和values()基本相同,但每个对象是⼀个元组
模型 类.objects.reverse() QuerySet 对排序的结果反转
模型类.objects.only(字段) QuerySet 只显示指定字段
模型 类.objects.defer(字段) QuerySet 去除指定字段
模型类.objects.get() 模型对象 返回⼀个满⾜条件的对象; 如果没有找到符合条件的对象,会引发模 型类.DoesNotExist异常; 如果找到多个,会引发模型 类.MultiObjectsReturned 异常
模型类.objects.first() 模型对象 返回第⼀条数据
模型类.objects.last() 模型对象 返回最后⼀条数据
模型 类.objects.earliest() 模型对象 根据指定字段返回最早增加的记录
模型 类.objects.latest(field) 模型对象 根据field字段返回最近增加记录
模型类.objects.exists() bool 判断查询的数据是否存在
模型类.objects.count() int 返回查询集中对象的数⽬

非过滤器查询

.get非过滤器查询只能返回一条数据,返回一条或不返回都会报错。

查询结果集中记录数:

1
2
3
# 返回类型必须是QuerySet才能调用count
articles = myarticle.objects.all()
count = articles.count()

查询结果集中是否有记录:

1
2
3
# 开发很常用,用于避免错误处理
flag = myarticle.objects.filter(id=0).exists()
print (flag)

filter查询

相当于sql语句中where⼦句,在传参是无法使用关系运算符,它可以为filter、exclude和get⽅法提供参数。

基础语法:

属性名称__⽐较运算符=值 #是两个下划线

filter支持多个条件查询,使用英文逗号分割多个条件:

1
myarticle.objects.filter(id__lt=50, id__gte=20)
操作符 含义
=或exact 精确判等 name=’admin’
iexact 不区分⼤⼩写判等 name__iexact=’Admin’
gt 大于 uid__gt=5
gte 大于等于 uid__gte=5
lt 小于 uid__lt=5
lte 小于等于 uid__lte=5
contains 模糊查询,等价like ‘% 值%’ name__contains=’Ad’
icontains 不区分⼤⼩写的模糊查 询 name__icontains=’ad’
startswith 以什么开头 name__startswith=’a’
istartswith 不区分⼤⼩写的以什么开头 name__istartswith=’A’
endswith 以什么结尾 name__endswith=’n’
iendswith 不区分⼤⼩写的以什么结尾 name__iendswith=’N’
isnull 判空,是否为空(等价 = None) name__isnull=True
in 包含 uid__in = [1,2,3] #in后⾯必须是可迭 代对象
regex 正则匹配 uname__regex= r’^a
iregex 不区分大小写的正则匹配 uname__iregex= r’^a

统计查询

需要先导⼊模块:

1
from django.db.models import Max,Min,Sum,Avg,Count
  • 聚合查询:对多⾏查询结果的⼀列进⾏操作
1
2
3
4
#统计记录总数: select count(*) from user 
User.objects.aggregate(Count('uid')) #{'uid__count': 4}
User.objects.aggregate(Max('uid')) #{'uid__max': 5}
User.objects.aggregate(Min('uid')) #{'uid__min': 2}
  • 分组统计
1
2
3
4
5
6
7
8
#等价sql: select type,count(*) from user group by type
res = User.objects.values('type').annotate(Count('uid'))
#统计结果: [{'type': '普通⽤户', 'uid__count': 3}, {'type': '超级管理
', 'uid__count': 1}]
#查看⽣成的sql语句
print(res.query)
#SELECT `user`.`type`, COUNT(`user`.`uid`) AS `uid__count` FROM
`user` GROUP BY `user`.`type` ORDER BY NULL

Q对象和F对象

需要先导⼊模块:

1
from django.db.models import Q,F
  • Q对象可以对关键字参数进⾏封装,从⽽更好的应⽤多个查询,可以组合& (and)、|(or)、~(not)操作符。
1
2
3
4
#原⽣sql:select * from user where uid = 2 or uid = 3
User.objects.filter(Q(uid=2)|Q(uid=3))
User.objects.filter(Q(uid__gte=2) & Q(uid__lte=3))
User.objects.filter(~Q(uid__gte=2))
  • F对象:⽤于⽐较表中两个字段
1
2
#等价sql:select * from user where uid < type
User.objects.filter(uid__lte = F('type'))

原始sql

您可以使⽤它 模块类.objects.raw()来执⾏原始查询并返回模型实例,或者您可以完全避免模型层并直接执⾏⾃定义SQL。

使用原始sql语句可以执行任何sql语句(必须包含主键),和模型无关。

  • raw执行sql语句
1
2
3
4
5
6
7
8
9
10
users = User.objects.raw("select * from user")
users = User.objects.raw("select * from user where
username='{}'".format('单强'))
print("select * from user where username='{}'".format('单强'))
users = User.objects.raw("select * from user where
username='{}'".format('单强'))
users = User.objects.raw("select * from user where username=%s",
["sddfsdf' or '1"])
print(list(users))
print(type(users))
  • ⾃定义sql
1
2
3
4
5
6
7
8
9
10
11
12
13
from django.db import connection
# with语句相当与cursor= connection.cursor() 和 cursor.close(),简化了语
with connection.cursor() as cursor:
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s",
[para])
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [para2])
row = cursor.fetchone()
# 返回列表套字典
with connection.cursor() as cursor:
cursor.execute("select * from publisher")
columns = [col[0] for col in cursor.description]
res = [dict(zip(columns, row)) for row in cursor.fetchall()]
print(res)

模型成员

模型类和数据库中表对应,模型类的对象和记录对象,模型类本身没有数据库访问 功能,但模型类中有⼀个Manager类的对象,通过管理器对象可以实现和数据库的 访问。

当我们没有为模型类定义管理器时,Django会为模型类⽣成⼀个名为objects的管 理器,⾃定义管理器后,Django不再⽣成默认管理器objects。

管理器是Django的模型进⾏数据库操作的接⼝,Django应⽤的每个模型都拥有⾄ 少⼀个管理器。Django⽀持⾃定义管理器类,继承⾃models.Manager。

⾃定义管理器类主要⽤于两种情况:

  • 修改原始查询集
  • 向管理器类中添加额外的⽅法,如向数据库中插⼊数据。

重命名管理器

在模型类中⾃定义⼀个新的管理器,则原有的objects管理器不会存在,以后对数 据库的操作使⽤⾃⼰定义的管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
#模型类
class Artical(models.Model):
aid = models.AutoField(primary_key=True)
title = models.CharField(max_length=100,null=False)
content = models.TextField(max_length=10000,null=True)
....
art_manager = models.Manager() #⾃定义了⼀个新的管理器,名字为
art_manager
#views
def article_get(request):
articles = Artical.art_manager.all() #使⽤art_manager进⾏查询
return render(request,"articlelist.html",context=
{'articls':articles})

自定义管理器

  • 修改原始查询集(由all()获取的查询集)
    • 修改管理器的get_queryset⽅法,可以改变all⽅法返回的原始查询集(实现自动过滤)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#⾸先⾃定义Manager的⼦类
class ArticleManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(ispublished=True) #
获取已发表的⽂章
#模型类
class Artical(models.Model):
....
objects = models.Manager() #可以有多个管理器
publishManager = ArticleManager()
#views
def article_publish(request):
published = Artical.publishManager.all()
return HttpResponse("已经发表{}".format(published[0].title))
  • 给管理器类中添加额外的⽅法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class ArticleManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(ispublished=True)
千锋python学院
#新增⼀个创建对象的⽅法
def
create(self,title,content,publishingdate,comments,likenum,ispubli
shed):
article = Artical()
article.title = title
article.content = content
article.publishingdate = publishingdate
article.comments = comments
article.likenum = likenum
article.ispublished = ispublished
article.save()
return article
#views.py中
def article_add(request):
# art = Artical(title='⼩时代',content="混乱的逻辑")
# art.save()
Artical.publishManager.create('中美贸易战','川朴⼀⾖⽐','2018-
10-8',0,0,1)
return HttpResponse("保存成功")

模型对应关系

关系数据库最强⼤大的地⽅方在于“关系”,也即表和表之间是有关联的,这种关联有三 种类型:

  • 一对一
  • 一对多
  • 多对多

一个学⽣生有⼀一个档案,一个档案属于一个学⽣生,那么学⽣生表和档案表就是一对一关 系。学生表是主表,档案表是从表,从表中有一个外键和学生表关联,并且要求外键取值唯一。对应关键字为:OneToOneField

一对一

  • 创建模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Student(models.Model):
sno = models.CharField(max_length=6,primary_key=True)
sname = models.CharField(max_length=100,null=False)
ssex = models.CharField(max_length=2,default='男',null=True)
sage = models.IntegerField(null=True)
sclass = models.CharField(max_length=10,null=True)
def __str__(self):
return "no:{},name:{}".format(self.sno,self.sname)
class Meta:
db_table = 'student'
class Archives(models.Model):
idcard = models.CharField(max_length=18, unique=True)
address = models.CharField(max_length=200,null=True)
# on_delete=models.CASCADE 级联删除,删除学⽣会连同档案⼀块删除
student = models.OneToOneField(Student, on_delete=models.CASCADE)
def __str__(self):
千锋python学院
增加数据
删除数据
正向查询
反向查询
return "{},{}".format(self.idcard,self.address)
class Meta:
db_table = 'archives'
  • 添加数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def addstudent(request):
student = Student()
student.sno = '180502'
student.sname = '杨康'
student.sage = 22
student.save()
return HttpResponse("增加了⼀个学⽣")
def addarchives(request):
stu = Student.objects.get(pk='180503')
arc = Archives()
arc.idcard = '130098384893838953'
arc.student = stu #学⽣对象必须已经保存到数据库,否则错误
arc.save()
return HttpResponse("增加档案")
  • 删除数据
1
2
3
4
def deletestudent(request):
student = Student.objects.get(pk='180503')
student.delete()
return HttpResponse("删除学⽣")
  • 正向查询
1
2
3
4
5
6
7
8
def findstudent(request):
# 获取学⽣信息
student = Student.objects.first()
print(student)
# 通过学⽣对象获取档案信息
archive = student.archives
print(archive)
return HttpResponse(student)
  • 反向查询
1
2
3
4
5
6
def findarchives(request):
#获取档案记录
archive = Archives.objects.first()
#通过档案获取关联学⽣信息
student = archive.student
return HttpResponse(student)
  • 跨关系查询
1
2
3
4
5
6
7
8
def lookup(request):
#根据档案查学⽣
# student = Student.objects.get(archives__pk=1)
student =
Student.objects.get(archives__idcard='13009488384383838')
#根据学⽣查档案
archive = Archives.objects.get(student__sno='180501')
return HttpResponse(archive)
  • on_delete
    • CASECADE 默认,默认级联删除数据
    • PROTECT 保护模式,当从表中存在级联记录的时候,删除主表记录会抛 出保护异常,从表中不存在级联数据的时候,是允许删除的
    • SET_XXX
      • NULL 外键字段本身必须允许为空
      • DEFAULT 外键字段本身有默认值
    • DO_NOTHING 什么都不做

一对多

⼀个出版社可以出版多本书,⼀本书只能被⼀个出版社出版。出版社和图书表属于 ⼀对多,⼀对多⼀般将主表中的主键并到从表中做外键。在模型中⽤ForeignKey表 示多对⼀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Publisher(models.Model):
pname = models.CharField(max_length=100,null=True)
def __str__(self):
return self.pname
千锋python学院
增加
删除和更新
正向查询
class Meta:
db_table = 'publisher'
class Book(models.Model):
bname = models.CharField(max_length=200,null=True)
#多对⼀模型通过ForeignKey表示多对⼀
#如果publisher定义在book之后,第⼀个参数应该⽤字符串'Publisher'
publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE,
null=True,
db_column='pid', #表中字段名
related_name='books') #通过出版社
查图书时使⽤的关系名
def __str__(self):
return self.bname
class Meta:
db_table = 'book'

多对多

⼀个买家可以购买多件商品,⼀件商品可以被多个买家购买,买家和商品之间构成 多对多关系,多对多关系必然会⽣成⼀张中间表:买家-商品表,记录商品和买家 的关系,该表包含商品表主键和买家表的主键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from django.db import models
# Create your models here.
class Buyer(models.Model):
bname = models.CharField(max_length=30)
level = models.IntegerField(default=1)
千锋python学院
购买商品
删除商品
正向查询
class Goods(models.Model):
gname = models.CharField(max_length=100)
price = models.FloatField()
buyer = models.ManyToManyField(Buyer) #这种写法⾃动⽣成第三张表,但
我们⽆法直接控制
def __str__(self):
return self.gname +" "+ str(self.price)
#⼿动创建中间表
class Orders(models.Model):
buyer =
models.ForeignKey(Buyer,on_delete=models.CASCADE,db_column='bid')
goods =
models.ForeignKey('Goods',on_delete=models.CASCADE,db_column='gid')
num = models.Integer(default=1)
class Goods(models.Model):
gname = models.CharField(max_length=100)
price = models.FloatField()
buyer = models.ManyToManyField(Buyer,through='Orders')

模型继承

django中的数据库模块提供了⼀个非常不错的功能,就是⽀持models的面向对 象,可以在models中添加Meta,指定是否抽象,然后进⾏继承。父类的嵌套类中有一个abstract参数,这个参数告诉Django怎么操作数据库。

当abstract为False时:DJango会创建两个表,一个子表一个父表,子表不会只有子类里的定义的属性

当abstract为True时:Django只会创建子表,不会创建父类表,生成表列为父类属性+子类属性

1
2
3
4
5
6
7
class Animal(models.Model):
# 列属性
class Meta:
abstract = True/False

class Dog(Animal):
# 列属性

分页

Paginator 分页器

分页是把数据按照一页多少个输出,Paginator⽤于分⻚,但Paginator并不具体管理具体的⻚的处理,而是使⽤Page 对象管理具体页面。

  • 创建分⻚器对象
1
paginator = Paginator(users, 10)	#paginator是返回对象,Paginator是Django提供的分页管理器,需要导入
  • 返回对象的属性
    • 对象.count 分页对象的个数
    • 对象.num_pages 总页数
    • 对象.page_range 页码的列表
  • ⽅法
    • page(num) 返回page对象 如果给定的页码不存在 则抛出异常

page 对象

page对象是调用创建分页管理器返回的对象的方法返回的对象,具体负责每页的处理,包括每页的数据,当前页的页码,是否有上⼀⻚ 或下⼀页等。

类别 名称 说明
属性 object_list 当前页码上的所有数据(QuerySet)
属性 number 当前页码值
属性 paginator 返回Paginator的对象
方法 has_next 是否有下⼀页
方法 has_previous 是否有上⼀页
方法 has_other_pages 是否有上⼀页或者下⼀页
方法 next_page_number 返回下⼀页的页码
方法 previous_page_number 返回上⼀页的页码
方法 len 返回当前页数据的个数

实例

  • 视图代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def page(request, page=1):
users = User.objects.all()
paginator = Paginator(users, 20)
num_pages = paginator.num_pages
pager = paginator.page(page)
page_list = pager.object_list
number = pager.number
next_page = page + 1
if next_page > num_pages:
next_page = 1
previous_page = page - 1
if previous_page == 0:
previous_page = num_pages
return render(request, 'list.html', locals())
  • 模板代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户列表</title>
</head>
<body>
<table border="1" cellspacing="0" width="100%">
<tr align="center">
<th>ID</th>
<th>用户名</th>
<th>密码</th>
</tr>
{% for user in page_list %}
<tr align="center">
<td>{{ user.id }}</td>
<td>{{ user.username }}</td>
<td>{{ user.password }}</td>
</tr>
{% endfor %}
</table>
<div align="center">
{% for page in paginator.page_range %}
<a href="{% url 'user:page' page=page%}">{{ page }}</a>
{% endfor %}
</div>
<div align="center">
<a href="/user/page/{{ previous_page }}">上一页</a> 共 {{ num_pages }} 页 当前第{{ number }}页 <a href="/user/page/{{ next_page }}">下一页</a>
</div>
</body>
</html>

Django 系列文章

Django基础学习:https://www.xpctf.cn/posts/24c5/
Django晋级学习:https://www.xpctf.cn/posts/2f99/
Django模型学习:https://www.xpctf.cn/posts/d0b4/
Django会话学习:https://www.xpctf.cn/posts/7490/
Django Form学习:正在写