Django 模型(Model)

1. 模型简介

2. 定义模型

3. 模型成员&管理器

4. 模型查询

 

 

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 中添加上述代码。

开发流程

  1. 在 models.py 中定义模型类,要求继承自 models.Model。
  2. 把应用加入 settings.py 文件的 installed_app 项。
  3. 迁移:生成迁移文件;执行迁移并生成表(迁移的目的是映射模型类与表。如果模型类与表的映射关系已存在,则无需迁移)。
  4. 使用模型类进行 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='')  # 查找标题包含“传”的数据
  • startswithendswith:匹配开头或结尾,大小写敏感。
filter(btitle__endswith='')

在前面加个 i 表示不区分大小写,如 iexact、icontains、istarswith、iendswith。

  • isnullisnotnull:是否为 null。
filter(btitle__isnull=False)
  • in:是否包含在范围内。
filter(pk__in=[1, 2, 3, 4, 5])
  • gtgte、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

 

posted @ 2021-04-03 22:06  Juno3550  阅读(406)  评论(0编辑  收藏  举报