Django 模型(Model)
1. 模型简介
2. 定义模型
3. 模型成员&管理器
4. 模型查询
- 1)查询集方法(select)
- 2)限制查询集(limit)
- 3)查询集缓存
- 4)字段查询&比较运算符(where)
- 5)聚合函数
- 6)F 对象(两字段值比较)
- 7)Q 对象(逻辑运算 and、or、not)
1. 模型简介
ORM 简介
MVC 框架中一个重要的部分就是 ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库。即直接面向对象操作数据,无需考虑 sql 语句。
ORM 是“对象-关系-映射”的简称,主要任务是:
- 根据对象的类型生成表结构。
- 将对象(或对象列表)的操作,转换为 sql 语句。
- 将 sql 查询到的结果转换为对象(或对象列表)。
这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动。
Django 中的模型包含了存储数据的字段和约束,对应着数据库中唯一的表。
使用 Mysql 数据库的环境配置
创建数据库
create databases modeldemo charset=utf8
打开应用的 settings.py 文件,修改 DATABASES 项:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'modeldemo', # 使用的Mysql库名 'USER': '用户名', 'PASSWORD': '密码', 'HOST': '数据库服务器ip,本地可以使用localhost', 'PORT': '端口,默认为3306', } }
安装 python mysql API
python3
pip install pymysql
且要在项目的 __init__.py 中添加:
import pymysql
pymysql.version_info = (1, 4, 13, "final", 0) # 指定版本。在出现“mysqlclient 1.4.0 or newer is required; you have 0.9.3.”报错时加上此行
pymysql.install_as_MySQLdb()
否则会出现报错:Error loading MySQLdb module: No module named 'MySQLdb'。
python2
pip install MySQL-python
且不需要在 __init__.py 中添加上述代码。
开发流程
- 在 models.py 中定义模型类,要求继承自 models.Model。
- 把应用加入 settings.py 文件的 installed_app 项。
- 迁移:生成迁移文件;执行迁移并生成表(迁移的目的是映射模型类与表。如果模型类与表的映射关系已存在,则无需迁移)。
- 使用模型类进行 crud(增删改查)操作。
2. 定义模型
在模型中定义属性,会生成表中的字段。
Django 根据属性的类型确定以下信息:
- 当前选择的数据库支持字段的类型(核心)。
- 渲染管理站点表单时使用的默认 html 控件。
- 在管理站点最低限度的验证。
Django 会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则 Django 不会再生成默认的主键列。
属性命名限制:
- 不能是 python 的保留关键字。
- 由于 Django 的查询方式,不允许带有连续的下划线。
1)定义属性
定义属性时,需要明确字段类型。字段类型被定义在 django.db.models.fields 目录下,为了方便使用,被导入到了 django.db.models 中。
使用方式:
from django.db import models
通过 models.Field 创建字段类型的对象,赋值给属性。如:
title = models.CharField(max_length=20)
若想对重要数据都做逻辑删除而不做物理删除,实现方法是定义 isDelete 属性,类型为 BooleanField,默认值为 False。
2)字段类型
- AutoField:一个根据实际 id 自动增长的 IntegerField,通常不指定。
- 如果不指定,一个主键字段将自动添加到模型中。
- BooleanField:true/false 字段,此字段的默认表单控制是 CheckboxInput。
- NullBooleanField:支持 null、true、false 三种值。
- CharField(max_length=最大字符长度):字符串,默认的表单样式是 TextInput。
- TextField:大文本字段,一般超过 4000 字符时使用,默认的表单控件是 Textarea。
- IntegerField:整数。
- DecimalField(max_digits=None, decimal_places=None):使用 python 的 Decimal 实例表示的十进制浮点数。
- DecimalField.max_digits:位数总数。
- DecimalField.decimal_places:小数点后的数字位数。
- FloatField:用 python 的 float 实例来表示的浮点数。
- DateField[auto_now=False, auto_now_add=False]):使用 python 的 datetime.date 实例表示的日期。
- 参数 DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为 false。
- 参数 DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为 false。
- 该字段默认对应的表单控件是一个 TextInput. 在管理员站点添加了一个 JavaScript 写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的 invalid_date 错误消息键。
- auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果。
- TimeField:使用 python 的 datetime.time 实例表示的时间,参数同 DateField。
- DateTimeField:使用 python 的 datetime.datetime 实例表示的日期和时间,参数同 DateField。
- FileField:一个上传文件的字段。
- ImageField:继承了 FileField 的所有属性和方法,但对上传的对象进行校验,确保它是个有效的 image。
3)字段选项
通过字段选项,可以实现对字段的约束。实现方式是通过字段对象的关键字参数指定。
- null:如果为 True,Django 将空值以 NULL 存储到数据库中,默认值是 False。
- blank:如果为 True,则该字段允许为空白,默认值是 False。
- 对比:null 是数据库范畴的概念,blank 是表单验证证范畴的。
- db_column:字段的名称,如果未指定,则使用属性的名称。
- db_index:若值为 True, 则在表中会为此字段创建索引。
- default:字段的默认值(遗留问题:该选项在数据库中未生效,但在对象操作时有效)。
- primary_key:若为 True, 则该字段会成为模型的主键字段。
- unique:如果为 True, 这个字段在表中必须有唯一值。
4)关系
关系的类型包括:
- ForeignKey:一对多,将字段定义在多的一端中。
- ManyToManyField:多对多,将字段定义在两端中。
- OneToOneField:一对一,将字段定义在任意一端中。
用一访问多:对象.模型类小写_set
bookinfo.heroinfo_set
用一访问一:对象.模型类小写
heroinfo.bookinfo
访问 id:对象.属性_id
heroinfo.book_id
5)元选项
在模型类中定义类 Meta,用于设置元信息。
- 元信息 db_table:定义数据表名称,推荐使用小写字母。
- 数据表的默认名称如下:
<app_name>_<model_name>
- ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表。
class BookInfo(models.Model): ... class Meta(): ordering = ['id']
- 字符串前加 - 表示倒序,不加 - 表示正序。
class BookInfo(models.Model): ... class Meta(): ordering = ['-id']
注意:排序会增加数据库的空间开销。
6)范例
创建 ModelDemo 项目,并创建 book_info 应用,使用 mysql 数据库。
定义图书和英雄模型:
1 from django.db import models 2 3 4 # 定义图书模型 5 class BookInfo(models.Model): 6 7 title = models.CharField(max_length=20) 8 public_date = models.DateField(db_column="pub_date") # 设置在数据库中的实际列名称 9 read_num = models.IntegerField(default=0) # 阅读量 10 comment_num = models.IntegerField(null=False) # 评论数 11 isDelete = models.BooleanField(default=False) # 只做逻辑删除,不做物理删除 12 13 class Meta: 14 db_table = "book_info" # 定义表名 15 16 17 # 定义英雄模型 18 class HeroInfo(models.Model): 19 20 name = models.CharField(max_length=20) 21 gender = models.BooleanField(default=True) 22 content = models.CharField(max_length=1000) # 对英雄的描述 23 isDelete = models.BooleanField(default=False) 24 book = models.ForeignKey(BookInfo)
执行迁移:
python manage.py makemigrations
python manage.py migrate
迁移完成后,在 mysql 查看生成的表信息:
测试数据
模型 BookInfo 的测试数据:
insert into book_info(title,pub_date,read_num,comment_num,isDelete) values ('射雕英雄传','1980-5-1',12,34,0), ('天龙八部','1986-7-24',36,40,0), ('笑傲江湖','1995-12-24',20,80,0), ('雪山飞狐','1987-11-11',58,24,0);
模型 HeroInfo 的测试数据:
insert into book_info_heroinfo(name,gender,book_id,content,isDelete) values ('郭靖',1,1,'降龙十八掌',0), ('黄蓉',0,1,'打狗棍法',0), ('黄药师',1,1,'弹指神通',0), ('欧阳锋',1,1,'蛤蟆功',0), ('梅超风',0,1,'九阴白骨爪',0), ('乔峰',1,2,'降龙十八掌',0), ('段誉',1,2,'六脉神剑',0), ('虚竹',1,2,'天山六阳掌',0), ('王语嫣',0,2,'神仙姐姐',0), ('令狐冲',1,3,'独孤九剑',0), ('任盈盈',0,3,'弹琴',0), ('岳不群',1,3,'华山剑法',0), ('东方不败',0,3,'葵花宝典',0), ('胡斐',1,4,'胡家刀法',0), ('苗若兰',0,4,'黄衣',0), ('程灵素',0,4,'医术',0), ('袁紫衣',0,4,'六合拳',0);
3. 模型成员&管理器
1)类属性
objects(类)属性是 Manager 类型的对象,即管理器对象。
管理器 Manager
- 管理器是模型类的类属性,是 Django 的数据模型与数据库交互的接口,用于将对象与数据表映射。Django 的 ORM 本质上就是通过管理器实现的。
- 当定义模型类时没有指定管理器,则 Django 会为模型类提供一个名为 objects 的管理器。Django 应用的每个模型类都拥有至少一个管理器。
- 如果不想用默认的管理器,可自定义管理器。自定义管理器类主要用于两种情况:
- 情况一:增加模型类的创建方式。
- 情况二:更改管理器返回的查询集:通过重写 get_queryset() 方法。
范例:更改查询结果集
编写自定义管理器类并应用
1 from django.db import models 2 3 4 """自定义管理器""" 5 class BookInfoManager(models.Manager): 6 def get_queryset(self): # 查询操作都会调用此方法 7 # 在父类的默认查询结果上,通过filter()加上自定义的查询逻辑 8 return super(BookInfoManager, self).get_queryset().filter(isDelete=False) 9 10 11 # 定义图书模型 12 class BookInfo(models.Model): 13 14 title = models.CharField(max_length=20) 15 public_date = models.DateField(db_column="pub_date") # 设置在数据库中的实际列名称 16 read_num = models.IntegerField(default=0) # 阅读量 17 comment_num = models.IntegerField(null=False) # 评论数 18 isDelete = models.BooleanField(default=False) # 只做逻辑删除,不做物理删除 19 20 class Meta: 21 db_table = "book_info" # 定义表名 22 23 """应用管理器""" 24 book_raw_manager = models.Manager() # 默认管理器 25 book_my_manager = BookInfoManager() # 自定义管理器 26 27 28 # 定义英雄模型 29 class HeroInfo(models.Model): 30 31 name = models.CharField(max_length=20) 32 gender = models.BooleanField(default=True) 33 content = models.CharField(max_length=1000) # 对英雄的描述 34 isDelete = models.BooleanField(default=False) 35 book = models.ForeignKey(BookInfo)
修改测试数据
使用 python manage.py shell 测试
>>> from book_info.models import BookInfo >>> >>> BookInfo.book_raw_manager.all() # 使用默认管理器的查询结果:4条数据 [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>] >>> BookInfo.book_my_manager.all() # 使用自定义管理器的查询结果:仅返回isDelete为False的两条数据 [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>]
2)实例对象的创建
- 当创建实例对象时,Django 不会对数据库进行读写操作。当调用 save() 方法后才与数据库交互,将对象保存到数据库中。
- 使用关键字参数构造模型对象很麻烦,推荐使用下面的两种方式。
- 说明: _init _ 方法已经在基类 models.Model 中使用,在自定义模型中无法使用。
范例:创建实例对象的两种方式
1 from django.db import models 2 3 4 # 自定义管理器 5 class BookInfoManager(models.Manager): 6 7 def get_queryset(self): 8 # 在父类的默认查询结果上,通过filter()加上自定义的查询逻辑 9 return super(BookInfoManager, self).get_queryset().filter(isDelete=False) 10 11 """创建实例对象的方式一(官方推荐)""" 12 def create(self, title, public_date): 13 book = self.model() 14 book.title = title 15 book.public_date = public_date 16 book.read_num = 0 17 book.comment_num = 0 18 book.isDelete = False 19 return book 20 '''以下方式直接保存了对象,不需要调用save() 21 book = self.create(btitle=title, bpub_date=pub_date, bread=0, bcommet=0, isDelete=False) 22 return book 23 ''' 24 25 26 # 定义图书模型 27 class BookInfo(models.Model): 28 29 title = models.CharField(max_length=20) 30 public_date = models.DateField(db_column="pub_date") # 设置在数据库中的实际列名称 31 read_num = models.IntegerField(default=0) # 阅读量 32 comment_num = models.IntegerField(null=False) # 评论数 33 isDelete = models.BooleanField(default=False) # 只做逻辑删除,不做物理删除 34 35 class Meta: 36 db_table = "book_info" # 定义表名 37 38 # 应用管理器 39 book_raw_manager = models.Manager() # 默认管理器 40 book_my_manager = BookInfoManager() # 自定义管理器 41 42 """创建实例对象的方式二""" 43 @classmethod 44 def create(cls, title, public_date): 45 b = cls() 46 b.title = title 47 b.public_date = public_date 48 b.read_num = 0 49 b.comment_num = 0 50 b.isDelete = False 51 return b 52 53 54 # 定义英雄模型 55 class HeroInfo(models.Model): 56 57 name = models.CharField(max_length=20) 58 gender = models.BooleanField(default=True) 59 content = models.CharField(max_length=1000) # 对英雄的描述 60 isDelete = models.BooleanField(default=False) 61 book = models.ForeignKey(BookInfo)
测试
>>> from book_info.models import BookInfo >>> import datetime >>> >>> # 通过类方法创建对象 >>> b1 = BookInfo.create("楚留香1", datetime.date(1988, 3, 1)) >>> b1.save() >>> # 通过管理器的方法创建对象 >>> b2 = BookInfo.book_my_manager.create("楚留香2", datetime.date(1988, 3, 1)) >>> b2.save() >>>
3)实例方法
- str(self):重写 object 方法,此方法在将对象转换成字符串时会被调用。
- save():将模型对象保存到数据表中。
- delete():将模型对象从数据表中删除。
4. 模型查询
1)查询集方法(select)
- 查询集表示从数据库中获取的对象集合。
- 过滤器基于所给的参数限制查询的结果。
- 查询集可以含有零个、一个或多个过滤器。
- 从 sql 的角度,查询集和 select 语句等价,过滤器像 where 和 limit 子句。
惰性执行:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库。实际调用数据的情况如下:
- 迭代
- 序列化
- 与 if 合用
管理器调用查询方法会返回查询集。返回查询集的方法如下:
- all():返回所有数据。
- filter():返回符合条件的数据。
- exclude():返回与条件相反的数据。
- order_by():排序。
- values():一个对象构成一个字典{'属性': '值'},所有对象构成一个列表返回。
过滤器语法:
filter(键1=值1, 键2=值2)
等价于
filter(键1=值1).filter(键2=值2)
查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤。
value() 执行结果:
>>> BookInfo.book_my_manager.values() # 等价于 BookInfo.book_my_manager.all().values() [{'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 4, 'title': '雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}, {'id': 7, 'title': '楚留香1', 'public_date': datetime.date(1988, 3, 1), 'read_num': 0, 'comment_num': 0, 'isDelete': False}, {'id': 8, 'title': '楚留香2', 'public_date': datetime.date(1988, 3, 1), 'read_num': 0, 'comment_num': 0, 'isDelete': False}]
返回单个值的方法:
- get():返回单个满足条件的对象。
- 如果未找到,会引发"模型类.DoesNotExist"异常。
- 如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常。
- count():返回当前查询的总条数。
- first():返回第一个对象。
- last():返回最后一个对象。
- exists():判断查询集中是否有数据,如果有则返回 True。
2)限制查询集(limit)
- 返回的查询集列表,可以使用索引或切片的方式进行限制,等同于 sql 中的 limit 和 offset 子句。
- 注意:不支持负数索引。
- 使用下标后返回一个新的查询集,不会立即执行查询(惰性查询)。
- 如果获取一个对象,直接使用[0],等同于[0:1].get()。如果没有数据,[0] 引发 IndexError 异常,[0:1].get() 引发 DoesNotExist 异常。
>>> BookInfo.book_my_manager.all()[0] # 返回对象 <BookInfo: BookInfo object> >>> BookInfo.book_my_manager.all()[0:1].get() # 返回对象 <BookInfo: BookInfo object> >>> BookInfo.book_my_manager.all()[0:1] # 返回对象列表 [<BookInfo: BookInfo object>]
3)查询集缓存
每个查询集都包含一个缓存来最小化对数据库的访问。
在新建的查询集中,缓存为空。当首次对查询集求值时,会发生数据库查询,Django 便会将查询的结果存在查询集的缓存中,并返回请求的结果。之后若访问相同的查询集值时将重用缓存的结果。
无法使用缓存的情况:
这构成了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。
print([e.title for e in Entry.objects.all()]) print([e.title for e in Entry.objects.all()])
可以使用缓存的情况:
两次循环使用同一个查询集,第二次使用缓存中的数据。
querylist = Entry.objects.all() print([e.title for e in querylist]) print([e.title for e in querylist])
何时查询集不会被缓存:
当只对查询集的部分进行求值时会检查缓存,但是如果这部分不在缓存中,那么接下来查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存。如果这部分数据已经被缓存,则直接使用缓存中的数据。
querylist = Entry.objects.all() print([e.title for e in querylist[0:10]]) # 使用缓存求子集,但子集的查询结果不会存入缓存
4)字段查询&比较运算符(where)
以下语法作为方法 filter()、exclude()、get() 的参数,从而实现 where 子句。
属性名称__比较运算符=值
- exact:表示判等,大小写敏感;如果没有写“ 比较运算符”,表示判等。
filter(isDelete=False) # 等价于 filter(isDelete__exact=False)
- contains:是否包含,大小写敏感。
filter(btitle__contains='传') # 查找标题包含“传”的数据
- startswith、endswith:匹配开头或结尾,大小写敏感。
filter(btitle__endswith='传')
在前面加个 i 表示不区分大小写,如 iexact、icontains、istarswith、iendswith。
- isnull、isnotnull:是否为 null。
filter(btitle__isnull=False)
- in:是否包含在范围内。
filter(pk__in=[1, 2, 3, 4, 5])
- gt、gte、lt、lte:大于、大于等于、小于、小于等于。
filter(id__gt=3)
- year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算。
filter(public_date__year=1980)
filter(public_date__gt=date(1980, 12, 31))
- 关联关系的查询:处理 join 查询。
- 语法:模型类名__属性名__比较运算符
- 可反向使用,即在关联的两个模型中都可以使用。
>>> BookInfo.book_my_manager.filter(heroinfo__content__contains="八").values() # 查询英雄对象的描述字段中含有“八”的图书数据 [{'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}]
- 快捷查询的属性 pk:pk 表示 primary key,默认的主键是 id。
filter(pk__lt=6) # 查询主键为6的数据
- 对于 like 语句中使用的 %,在过滤器中无需转义。
filter(title__contains="%") # 等价于 where title like '%\%%',表示查找标题中包含 % 的数据。
5)聚合函数
使用 aggregate() 函数返回聚合函数的值。
- Count、Avg、Max、Min、Sum 的用法:
from django.db.models import Max >>> BookInfo.book_my_manager.aggregate(Max('public_date')) # 查找出版日期最晚的书 {'public_date__max': datetime.date(1988, 3, 1)}
- count 的一般用法:
>>> BookInfo.book_my_manager.aggregate(Count('public_date')) {'public_date__count': 4} >>> BookInfo.book_my_manager.count() # 直接得到数值 4
6)F 对象(两字段值比较)
- 可以使用模型的字段 A 与字段 B 进行比较,如果 A 写在了等号的左边,则 B 出现在等号的右边,需要通过 F 对象构造。
>>> from django.db.models import F >>> BookInfo.book_my_manager.filter(read_num__gt=F('comment_num')).values() # 查找阅读量 > 评论量的数据 [{'id': 4, 'title': '雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}] >>>
- django 支持对 F() 对象使用算数运算。
BookInfo.book_my_manager.filter(read_num__gt=F('comment_num')*2)
- F() 对象中还可以写作“模型类__列名”进行关联查询。
>>> BookInfo.book_my_manager.filter(isDelete=F('heroinfo__isDelete')).values() [{'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}, {'id': 4, 'title': ' 雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}, {'id': 4, 'title': '雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}, {'id': 4, 'title': '雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}, {'id': 4, 'title': '雪山飞狐', 'public_date': datetime.date(1987, 11, 11), 'read_num': 58, 'comment_num': 24, 'isDelete': False}]
- 对于 date/time 字段,可与 timedelta() 进行运算。
>>> from datetime.datetime import timedelta >>> >>> BookInfo.book_my_manager.filter(public_date__lt=F('public_date')+timedelta(days=1)) [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>]
7)Q 对象(逻辑运算 and、or、not)
需要进行 and、or、not 查询时,可以使用 Q() 对象。
- Q 对象(django.db.models.Q)用于封装一组关键字参数,这些关键字参数与“比较运算符”中的相同:
>>> from django.db.models import Q >>> >>> BookInfo.book_my_manager.filter(Q(pk__lt=2)).values() [{'id': 1, 'title': '射雕英雄传', 'public_date': datetime.date(1980, 5, 1), 'read_num': 12, 'comment_num': 34, 'isDelete': False}]
- Q 对象可以使用 &(and)、|(or)操作符组合起来。当操作符应用在两个 Q 对象时,会产生一个新的 Q 对象。
>>> # 实现逻辑与,三者等价 >>> BookInfo.book_my_manager.filter(pk__lt=10).filter(pk__gt=2) [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>] >>> BookInfo.book_my_manager.filter(pk__lt=10, pk__gt=2) [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>] >>> BookInfo.book_my_manager.filter(Q(pk__lt=10) & Q(pk__gt=2)) [<BookInfo: BookInfo object>, <BookInfo: BookInfo object>, <BookInfo: BookInfo object>] >>> >>> # 实现逻辑或 >>> BookInfo.book_my_manager.filter(Q(pk__lt=3) | Q(pk__gt=10)) [<BookInfo: BookInfo object>]
- 使用 ~ 操作符在 Q 对象前表示取反(not)。
>>> BookInfo.book_my_manager.filter(~Q(pk__lt=3)) # 表示主键不小于3