目录
ORM介绍
Django ORM (Object-Relational Mapping)是Django框架中用于与数据库进行交互的工具。它提供了一种方便的方式来执行数据库操作,而无需直接编写SQL语句。
Django ORM的核心理念是将数据库中的表映射为Python类,将表中的行映射为类的实例。开发者可以通过操作这些类和实例来执行数据库的增删改查操作。
ORM在业务逻辑层和数据库层之间充当了桥梁的作用。
Django ORM的一些主要特性:
-
数据模型定义:使用Django ORM,开发者可以通过定义Python类来描述数据库中的表结构。类的属性通常会映射到表的字段,而类的方法则用于定义数据库操作。
-
数据库迁移:Django ORM提供了强大的数据库迁移工具,可以轻松地在开发过程中对数据库进行版本管理。开发者可以通过迁移命令自动将数据模型更新到最新版本,而无需手动编写SQL语句。
-
查询语句生成:通过使用Django ORM提供的查询API,开发者可以使用Python代码来生成SQL查询语句。这种方式比手动编写SQL语句更安全、更易读、更易维护。
-
查询优化:Django ORM提供了一些查询优化的机制,如查询缓存和惰性查询等。这些机制可以帮助开发者提高查询性能,减少与数据库的交互次数。
-
事务管理:Django ORM支持事务的原子操作,开发者可以使用事务来确保一组数据库操作要么全部成功,要么全部失败。这样可以保证数据的一致性和完整性。
ORM的优势
ORM解决的主要问题是对象和关系的映射。它通常将一个类和一张表一一对应,类的每个实例对应表 中的一条记录,类的每个属性对应表中的每个字段。
ORM提供了对数据库的映射,不用直接编写SQL代码,只需操作对象就能对数据库操作数据。 让软件开发人员专注于业务逻辑的处理,提高了开发效率。
ORM的劣势
ORM的缺点是会在一定程度上牺牲程序的执行效率。
ORM的操作是有限的,也就是ORM定义好的操作是可以完成的,一些复杂的查询操作是完成不了。
ORM用多了SQL语句就不会写了,关系数据库相关技能退化...
Django项目使用MySQL数据库
要在Django项目中使用MySQL数据库,需要在项目的设置文件(settings.py)中进行配置。
pip install mysqlclient
接下来,在设置文件的DATABASES部分进行配置。您需要提供数据库的名称、用户名、密码、主机和端口等信息。将以下代码添加到设置文件中:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '<database_name>',
'USER': '<username>',
'PASSWORD': '<password>',
'HOST': '<host>',
'PORT': '<port>',
}
}
请确保将
<database_name>
、<username>
、<password>
、<host>
和<port>
替换为实际的数据库信息。分别是数据库名字,用户名称,数据库密码,ip地址,端口号默认3306
在与Django项目同名的目录下的init.py文件中写如下代码,告诉Django使用pymysql模块连接
import pymysql
pymysql.install_as_MySQLdb()
最后通过两条数据库迁移命令即可在指定的数据库中创建表 :
python3 manage.py makemigrations
python3 manage.py migrate
确保配置文件中的INSTALLED_APPS中写入我们创建的app名称
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"user_app"
]
如果想打印orm转换过程中的sql,需要在settings中进行如下配置:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
在终端执行脚本:
import os
if __name__ == __'main'__:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
import django
django.setup()
from app01 import models
books = models.Book.objects.all()
print(books)
Django支持MySQL5.5及更高版本。
Model
在Django中model是数据的单一、明确的信息来源。它包含了你存储的数据的重要字段和行为。通 常,一个模型(model)映射到一个数据库表。
- 每个模型都是一个Python类,它是django.db.models.Model的子类。
- 模型的每个属性都代表一个数据库字段。
字段
常用字段
AutoField
自增的整形字段,必填参数primary_key=True,则成为数据库的主键。无该字段时,django自动创 建。
一个model不能有两个AutoField字段。
IntegerField
一个整数类型。数值的范围是 -2147483648 ~ 2147483647。
CharField
字符类型,必须提供max_length参数。max_length表示字符的长度。
DateField
日期类型,日期格式为YYYY-MM-DD,相当于Python中的datetime.date的实例。
参数
auto_now:每次修改时修改为当前日期时间。
auto_now_add:新创建对象时自动添加当前日期时间。
auto_now和auto_now_add和default参数是互斥的,不能同时设置。
字段类型
AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models
class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)
class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647
BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
BooleanField(Field)
- 布尔值类型
NullBooleanField(Field):
- 可以为空的布尔值
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]
DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
- 浮点型
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
- 二进制类型
字段参数
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages
自定义错误信息(字典类型),从而定制想要显示的错误信息;
字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
如:{'null': "不能为空.", 'invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
max_length=32,
error_messages={
'c1': '优先错信息1', 'c2': '优先错信息2','c3': '优先错信息3',
},
validators=[
RegexValidator(regex='root_\d+', message='错误了',code='c1'),
RegexValidator(regex='root_112233\d+', message='又错误了',code='c2'),
EmailValidator(message='又错误了', code='c3'), ]
)
ForeignKey(ForeignObject) # ForeignObject(RelatedField)
to, # 要进行关联的表名
to_field=None, # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- models.CASCADE,删除关联数据,与之关联也删除
- models.DO_NOTHING,删除关联数据,引发错误IntegrityError
- models.PROTECT,删除关联数据,引发错误ProtectedError
- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
- models.SET,删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
def func():
return 10
class MyModel(models.Model):
user = models.ForeignKey(
to="User",
to_field="id"
on_delete=models.SET(func),)
related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】
如: obj.表名_set.all()
related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】
如:
models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
# 如:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5}
from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
db_constraint=True # 是否在数据库中创建外键约束
parent_link=False # 在Admin中是否显示关联数据
OneToOneField(ForeignKey)
to, # 要进行关联的表名
to_field=None # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
###### 对于一对一 ######
# 1. 一对一其实就是 一对多 + 唯一索引
# 2.当两个类之间有继承关系时,默认会创建一个一对一字段
# 如下会在A表中额外增加一个c_ptr_id列且唯一:
class C(models.Model):
nid = models.AutoField(primary_key=True)
part = models.CharField(max_length=12)
class A(C):
id = models.AutoField(primary_key=True)
code = models.CharField(max_length=1)
ManyToManyField(RelatedField)
to, # 要进行关联的表名
related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】
如: obj.表名_set.all()
related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】
如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
如:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5}
from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10))&Q(caption='root')
symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
# 做如下操作时,不同的symmetrical会有不同的可选字段
models.BB.objects.filter(...)
# 可选字段有:code, id, m1
class BB(models.Model):
code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=True)
# 可选字段有: bb, code, id, m1
class BB(models.Model):
code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=False)
through=None, # 自定义第三张表时,使用字段用于指定关系表
through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)
class Membership(models.Model):
group = models.ForeignKey(Group,on_delete=models.CASCADE)
person = models.ForeignKey(Person,on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
db_constraint=True, # 是否在数据库中创建外键约束
db_table=None, # 默认创建第三张表时,数据库中表的名称
id字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果 Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。
本示例中的CREATE TABLE SQL使用PostgreSQL语法进行格式化,但值得注意的是,Django会根据配置文件中 指定的数据库类型来生成相应的SQL语句。
ORM操作
QuerySet数据类型介绍:
QuerySet与惰性机制:所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对 象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。
QuerySet特点:
可迭代的
可切片
基本操作
# 增
models.Tb1.objects.create(c1 ='xx', c2 ='oo') # 增加一条数据,可以接受字典类型数据
**kwargs
obj = models.Tb1(c1 = 'xx' , c2 = 'oo')
obj.save()
# 查
models.Tb1.objects.get(id= 123) # 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.all() # 获取全部
models.Tb1.objects.filter``(name='seven') # 获取指定条件的数据
models.Tb1.objects.exclude(name='seven') # 去除指定条件的数据
# 删
# models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
# 改
models.Tb1.objects.filter(name = 'seven' ).update(gender = '0') # 将指定条件的数据更新,均支
# 持 **kwargs
obj = models.Tb1.objects.get(id = 1)
obj.c1 = '111'
obj.save() # 修改单条数据
查询操作:
1. all(): 查询所有结果
2. get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
3. filter(**kwargs): 包含与所给筛选条件相匹配的对象
4. exclude(**kwargs): 包含与所给筛选条件不匹配的对象
5. values(*field): 返回一个ValueQuerySet,得到的是一个可迭代的字典序列,不是一系列model的实例化对象
6. values_list(*field): 与values()非常相似,返回的是一个元组序列,values返回的是一个字典序列
7. order_by(*field): 对查询结果排序
8. reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
9. distinct(): 从返回结果中剔除重复记录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
10. count(): 返回数据库中匹配查询(QuerySet)的对象数量。
11. first(): 返回第一条记录
12. last(): 返回最后一条记录
13. exists(): 如果QuerySet包含数据,就返回True,否则返回False
返回QuerySet对象的方法有:
all() filter() exclude() order_by() reverse() distinct()
特殊的QuerySe
values() 返回一个可迭代的字典序列 values_list() 返回一个可迭代的元组序列
返回具体对象的
get() first() last()
返回布尔值的方法有:
exists()
返回数字的方法有
count()
单表查询之神奇的双下划线
1 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
2 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
3 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
4 models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
5 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
6 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and
7 类似的还有:startswith,istartswith, endswith, iendswith
8 date字段还可以:
9 models.Class.objects.filter(first_day__year=2020)
-
用于字段查询:双下划线可以用于指定字段的特定属性或条件。例如,
field__exact
表示字段的精确匹配,field__gt
表示字段的大于某个值的条件,field__contains
表示字段包含某个值的条件等。 -
用于关联查询:双下划线可以用于跨表查询,通过指定关联字段的名称和相关属性来实现。例如,
related_model__field
表示查询相关模型的指定字段。 -
用于日期和时间查询:双下划线可以用于对日期和时间字段进行查询。例如,
date_field__year
表示查询日期字段的年份,time_field__hour
表示查询时间字段的小时等。 -
用于查询聚合和注解:双下划线可以用于对查询结果进行聚合操作或添加注解。例如,
annotate_field__sum
表示对某个字段进行求和操作。
外键操作
正向查找
对象查找(跨表)
语法:
对象.关联字段.字段
# 示例
book_obj = models.Book.objects.first() # 第一本书对象
print(book_obj.publisher) # 得到这本书关联的出版社对象
print(book_obj.publisher.name) # 得到出版社对象的名称
字段查找(跨表)
语法:
关联字段__字段
# 示例
print(models.Book.objects.values_list("publisher__name"))
反向操作
对象查找
语法:
obj.表名_set
# 示例
publisher_obj = models.Publisher.objects.first() # 找到第一个出版社对象
books = publisher_obj.book_set.all() # 找到第一个出版社出版的所有书
titles = books.values_list("title") # 找到第一个出版社出版的所有书的书名
字段查找
语法:
表名___字段
# 示例
titles = models.Publisher.objects.values_list("book__title")
ManyToManyField
class RelatedManager
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
它存在于下面两种情况:
1. 外键关系的反向查询
2. 多对多关联关系
简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。
方法
create()
创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。
>>> import datetime >>> models.Author.objects.first().book_set.create(title="python入门", publish_date=datetime.date.today())
add()
把指定的model对象添加到关联对象集中。
添加对象
author_objs = models.Author.objects.filter(id__lt=3) models.Book.objects.first().authors.add(*author_objs)
添加id
models.Book.objects.first().authors.add(*[1, 2])
set()
更新model对象的关联对象。
book_obj = models.Book.objects.first() book_obj.authors.set([2, 3])
remove()
从关联对象集中移除执行的model对象
book_obj = models.Book.objects.first() book_obj.authors.remove(3)
clear()
从关联对象集中移除一切对象。
book_obj = models.Book.objects.first() book_obj.authors.clear()
注意: 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
举个例子:
ForeignKey字段没设置null=True时,
class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to=Publisher)
没有clear()和remove()方法:
models.Publisher.objects.first().book_set.clear() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'RelatedManager' object has no attribute 'clear' # 报错信息
当ForeignKey字段设置null=True时,
class Book(models.Model): name = models.CharField(max_length=32) publisher = models.ForeignKey(to=Class, null=True)
此时就有clear()和remove()方法:
models.Publisher.objects.first().book_set.clear()
注意:
对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的 任何一端,都不需要再调用save()方法。
聚合查询和分组查询
聚合
aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。 键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生 成出来的。
用到的内置函数:
from django.db.models import Avg, Sum, Max, Min, Count
示例:
from django.db.models import Avg, Sum, Max, Min, Count models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333}
如果你想要为聚合值指定一个名称,可以向聚合子句提供它。
models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333}
如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道 所有图书价格的最大值和最小值,可以这样查询:
models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
分组
我们在这里先复习一下SQL语句的分组。 假设现在有一张公司职员表:
我们使用原生SQL语句,按照部门分组求平均工资:
select dept,AVG(salary) from employee group by dept;
ORM查询:
from django.db.models import Avg Employee.objects.values("dept").annotate(avg=Avg("salary").values("dept", "avg")
SQL查询:
select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;
ORM查询:
from django.db.models import Avg models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")
F查询和Q查询
在ORM中,F查询和Q查询是两种常用的查询方法。
F查询
F查询是通过指定字段来进行查询,它允许我们只查询所需的字段,而不需要返回整个对象。例如,假设我们有一个User模型,它有name和age两个字段,我们可以使用F查询来查询年龄大于等于18的用户
from django.db.models import F users = User.objects.filter(age__gte=F('age')+18)
在这个例子中,
age__gte=F('age')+18
表示查询年龄大于等于age+18
的用户。Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
Q查询
Q查询是通过使用逻辑运算符来进行查询,它允许我们根据多个条件来组合查询。例如,假设我们有一个User模型,它有name和age两个字段,我们可以使用Q查询来查询名字包含"John"且年龄大于等于18的用户:
from django.db.models import Q users = User.objects.filter(Q(name__contains='John') & Q(age__gte=18))
在这个例子中,
Q(name__contains='John')
和Q(age__gte=18)
表示查询名字包含"John"且年龄大于等于18的用户。
F查询和Q查询可以结合使用,以满足更复杂的查询需求。无论是F查询还是Q查询,都可以提高查询的灵活性和效率。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了ORM的使用