前言
在Django框架中,数据是应用的核心。其强大的ORM(对象关系映射)系统使得数据操作变得直观且高效。本文将带您领略Django ORM的精髓,包括模型类字段与属性的设定、元选项的配置、以及增删改查等基础操作。特别地,我们将聚焦链式过滤条件和QF查询,让您轻松构建复杂查询。同时,深入介绍QuerySet,这个ORM的核心组件,带您领略其强大的数据处理能力。
提示:以下是本篇文章正文内容,下面案例可供参考
一、模型类字段
每一个字段都是
Field
基类的一个实例(Field
类用来建立字段与数据库之间的映射)
1.BooleanField
True/False 字段,默认值为 None
BooleanField(**options)
2.CharField
字符串字段
CharField(max_length=None) # max_length 设置最大的字符数长度限制
3.DateField
以
datetime.date
实例表示的日期 2013-08-01
DateField(auto_now=False, auto_now_add=False,**options) ''' auto_now: 该值为 True 时,每次在保存数据对象时,自动设置该字段为当前时间,也可以理解为自动更新最后一次修改时间 auto_now_add: 该值为 True 时,该字段设置在第一次数据对象创建时,可以记录当前字段创建的时间值 '''
注意:避免矛盾,
auto_now
,auto_now_add
,default
不能同时出现,一个字段属性只能有其中一条设置,当设置了auto_now
,或auto_now_add
时,也会让该字段默认具有blank=True
(字段可以为空)属性
4.DatetimeField
以
datetime.datetime
实例表示的日期和时间
DatetimeField(auto_now=False, auto_now_add=False,**options) # auto_now_add: 创时使用当前时间 注册时间 # auto_now: 修改时自动更新为当前时间 用户上次登陆,修改ip # 和 DateField 具有相同的字段属性
5.DecimalField
以Decimal实例表示的十进制浮点数类型
DecimalField(max_digits=None,decimal_places=None, **options) ''' max_digits: 位数总数,包括小数点后的位数,必须大于 decimal_places 参数 decimal_places: 小数点后的数字数量,精度 '''
6.FloatField
使用
float
实例来表示的浮点数
FloatField(**options)
7.IntegerField
一个整数,范围由
-2147483648
到2147483647
IntegerField(**options)
二、字段属性
1.null
如果该值为
True
,将在数据库中将控制存储为NULL
# app/models.py下的模型类中 title = models.CharField(max_length=100,null=True) # 允许title为空
2.blank
如果该值为
True
,则在验证时该字段值可以为空
null
为数据库存储层面可以为空,而blank
为表单验证层面可以填写空值
3.choices
一个二元组的列表或元组,元组中第一个值为真正在数据库中存储的值,第二个值为该选项的描述
class studentModel(models.Model): GENDER_CHOICES = [ (1, '男'), (2, '女'), (3, '保密'), ] gender = models.IntegerField(verbose_name='性别', default=3, choices=GENDER_CHOICES)
4.db_column
数据库中用来表示该字段的名称,如果未指定,那么 Django 将会使用
Field
名作为字段名
5.db_index
当该值为
True
时,为该字段创建索引
6.default
为字段提供默认值
7.primary_key
设置该值为
True
时,该字段成为模型的主键字段,一个模型类同时只能有一个主键如果一个表中不存在任意一个设置好的主键字段,django 会自动设置一个自增的
AutoField
字段来充当主键,该值可以用pk
,id
方式获取。主键的设置还意味着,null=False
,unique=True
8.unique
如果该值为
True
,代表这个数据在当前的表中有唯一值,这个字段还会在模型层验证存储的数据是否唯一
9.verbose_name
给字段的一个可读性更高的名称,如果没有设置该值,字段名中的下换线转换成空格,作为当前字段的数据库中名称
三、模型类元选项
在模型类的Meta
类中,可以提供一系列的元选项,可以方便对该模型类进行属性设置或约束等。
class TestTable(models.Model): … class Meta: db_table= 'test' verbose_name_plural = '测试表' …
1.abstract
代表当前模型类为抽象基类,不会创建真正的数据表,只是为了其他模型类继承使用
abstract = True
2.app_label
当模型类被定义在了其他 app 下,这个属性用来描述当前表属于哪个 app 应用
app_label = "MyApp"
3.abstract
代表当前模型类为抽象基类,不会创建真正的数据表,只是为了其他模型类继承使用
abstract = True
4.db_table
当前模型类所对应的表名,未设置时,django 默认将表名与 app 名由下划线组成,作为表名
这个表名为真实在数据库中所使用的,所以该元选项的使用应在数据表创建之前
如果在表已经存在的情况下去修改,会导致数据库内表与模型类表名不一致而查找不到报错
5.ordering
1.当前表中的数据存储时的排序规则,这是一个字段名的字符串,可以是一个列表或元组;
2.每一个字符串前可以使用"
-
“来倒序排序,使用”?
"随机排序3.ordering 排序规则的添加,也会增加数据库的开销
ordering = ['-birthday', 'age'] #先按照 birthday 倒序排序,再按照 age 字段进行排序。
6.verbose_name
一般设置该表展示时所用的名称,名称被自动处理为复数,字符串后加一个"s"
ordering = ['-birthday', 'age'] #先按照 birthday 倒序排序,再按照 age 字段进行排序。
7.verbose_name_plural
与
verbose_name
功能相同,但是不会自动在字符串后加"s
"以表复数设置表的复数名称
8.ordering
1.当前表中的数据存储时的排序规则,这是一个字段名的字符串,可以是一个列表或元组;
2.每一个字符串前可以使用"
-
“来倒序排序,使用”?
"随机排序3.ordering 排序规则的添加,也会增加数据库的开销
ordering = ['-birthday', 'age'] #先按照 birthday 倒序排序,再按照 age 字段进行排序。
四、ORM增删改查
0.ORM的增删改查
# 增 1、obj = 模型类(属性=数据) obj.save() 2、模型类.objects.create(属性=数据) # 查 模型类.objects.all() 模型类.objects.get() 模型类.objects.filter() # 删 obj = 模型类.objects.get() obj.delete() 模型类.objects.filter(属性=条件).delete() # 改 obj = 模型类.objects.get() obj.属性=新值 obj.save() 模型类.objects.filter(属性=条件).update(属性=新值) 注意: 1.增:save()没有返回值,create()一步到位 2.查:all()、filter()、exclude()、get()、 3.查找时的一些特殊字段的使用: order_by() Person.objects.order_by('age') Person.objects.all().order_by('-age') 4.count():返回数据库中对应字段的个数,并且该函数永远不会引发异常 5.values():返回一个查询集结果,但是迭代访问时返回的是字典,而不是数据实例对象 models.Person.objects.all().values() models.Person.objects.values() 6.链式过滤条件
1.增加数据
新建一个子应用 news
# news/models.py from django.db import models # Create your models here. class newsModel(models.Model): title = models.CharField(max_length=100) content = models.TextField() visit_num = models.IntegerField(default=0) good_num = models.IntegerField(default=0) pub_date = models.DateTimeField(default='2024-5-30') def __str__(self): return self.title class Meta: db_table = 'news' verbose_name_plural = '新闻表'
创建对象:
# news/views def addData(request): # 添加数据的两种方式 # n1 = newsModel() # n1.title = "方式一:新闻标题" # n1.content = "方式一:新闻内容" # n1.save() n2 = newsModel.objects.create(title="方式二:新闻标题",content="方式二:新闻内容") return HttpResponse('{"message":"增加数据成功!"}',content_type="application/json")
2.查找对象
def queryData(request): # 1.查询所有,并返回结果集(以id为降序查询) # n1 = newsModel.objects.all().order_by('-id') # for i in n1: # print(i.title) # print(i.content) # print(i.visit_num) # print(i.good_num) # print(i.pub_date) # print("-"*16) # 2.使用get查询的时候,默认使用id,如果使用其他数据查询,保证数据唯一 # try: # n2 = newsModel.objects.get(id=2) # except Exception as e: # print(e) # 3.返回的也是根据条件过滤的结果集(阅读量大于100,点赞量大于50) n3 = newsModel.objects.filter(visit_num__gt=100).filter(good_num__gt=50) for i in n3: print(i.title) print(i.content) print(i.visit_num) print(i.good_num) print(i.pub_date) print("-"*16) #4.查找符合条件以外的数据 # n4 = newsModel.objects.exclude(good_num=0) return HttpResponse('{"message":"返回数据展示!"}',content_type="application/json")
查询中用到的一些字段:
a.order_by(*field)
默认情况下,数据表使用模型类中的 Meta 中指定的 ordering 选项进行排序
也可以通过使用 order_by 函数进行查询结果的排序
Person.objects.order_by('age') Person.objects.all().order_by('-age')
b.count()
返回数据库中对应字段的个数,并且该函数永远不会引发异常
models.Person.objects.filter(age=20).count() Person.objects.count()
c.order_by(*field)
默认情况下,数据表使用模型类中的 Meta 中指定的 ordering 选项进行排序
也可以通过使用 order_by 函数进行查询结果的排序
Person.objects.order_by('age') Person.objects.all().order_by('-age')
注意:所以有时使用已生产好的结果集,通过len*函数获取长度,这种方式效率会更高;
count
方法的调用会导致额外的数据库查询
d.values(*fields)
返回一个查询集结果,但是迭代访问时返回的是字典,而不是数据实例对象
models.Person.objects.all().values() models.Person.objects.values()
3.链式过滤条件
contains:
大小写敏感的匹配查询,也是 like,注意转换后查询条件的两侧都有%
Person.objects.filter(name__contains='好')
icontains:
大小写不敏感的匹配查询
Person.objects.filter(name__icontains='好')
range:
在某个范围内进行查询
Person.objects.filter(id__range=(1,6))
in:
在某个范围内进行查询
Person.objects.filter(id__in=(1,6)) Person.objects.filter(id__in=[1,6])
exact:
如果在查询过程中,没有提供查询类型(没有
双下划线
),那么查询类型就会被默认指定为exact
,这是一种严格查找的方式,用来在数据库中查找和查询时的关键词参数完全一致的内容
Person.objects.filter(account='root') Person.objects.filter(account__exact='root')
iexact:
忽略大小写的匹配
Person.objects.filter(account__iexact='root') #匹配到的结果可能是 Root,ROot,ROOt,ROOT
startswith、endswith:
分别匹配开头和结尾,区分大小写
Person.objects.filter(passwd__startswith='admin') # 匹配以 admin 开头的数据
istartswith、iendswith:
分别匹配开头和结尾,忽略大小写
Person.objects.filter(passwd__istartswith='admin') 匹配以不区分大小写的字符串 admin 为开头的数据
gte:
大于或等于
Person.objects.filter(reg_data__gte=datetime.date.today)
lte:
小于或等于
Person.objects.filter(reg_data__lte=datetime.date.today)
4.修改对象
def updateData(request): # 1.查询单个数据,进行修改(id = 1) n1 = newsModel.objects.get(id=1) n1.title = "修改后的新闻标题" n1.content = "修改后的新闻内容" n1.save() #2.通过过滤结果集,修改数据 # n2 = newsModel.objects.filter(visit_num=0).update(visit_num=150) # n3 = newsModel.objects.filter(good_num=0).update(good_num=75) # print(n2) # print(n3) return HttpResponse('{"message":"修改数据成功!"}',content_type="application/json")
5.删除对象
def removeData(request): # 1.全部删除 # newsModel.objects.all().delete() # 2.先get查询,再删除数据(id = 2) n1 = newsModel.objects.get(id=2) n1.delete() # 3.根据filter过滤,删除查询到的数据(点赞量等于0的数据) # n2 = newsModel.objects.filter(good_num=0).delete() # print(n2) return HttpResponse('{"message":"删除数据成功!"}',content_type="application/json")
6.ORM的Q、F查询
Q查询:
之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢?
- 使用F对象,被定义在
django.db.models
中。- 可以在F对象上使用算数运算。
from django.db.models import F F('属性名') # 注意:属性名是字符串形式 1.查询阅读量大于评论量的图书 Book.objects.filter(bread__gt=F('bcomment')) 2.查询阅读量是评论量2倍的图书 Book.objects.filter(bread=F('bcomment')*2) 3.查询阅读量比评论量多100的图书 Book.objects.filter(bread=F('bcomment')+100)
F查询:
- 多个过滤器逐个调用表示逻辑与
and
关系,同sql语句中where部分的and关键字。- 如果需要实现逻辑或
or
的查询,需要使用Q对象结合逻辑运算符,Q对象被义在django.db.models
中。- Q对象可以使用
&
、|
连接,&
表示逻辑与,|
表示逻辑或。
from django.db.models import Q Q(属性名__运算符=值) # 注意: 属性名不是字符串,不能加引号 1.查询id阅读量大于20且id小于3的图书 Book.objects.filter(bcomment__gt=20).filter(id__lt=3) # 多个过滤器连续操作 Book.objects.filter( Q(bcomment__gt=20) & Q(id__lt=3) ) # 使用Q对象和逻辑运算符 2.查询阅读量大于20,或编号小于3的图书 Book.objects.filter( Q(bcomment__gt=20) | Q(id__lt=3) ) # 只能使用Q对象
7.QuerySet
查询结果集:表示从数据库中获取的对象集合。
当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):
- all():返回所有数据。
- filter():返回满足条件的数据。
- exclude():返回满足条件之外的数据。
- order_by():对结果进行排序。
# 1.惰性查询-懒加载 # 2.缓存 queryset[0].name queryset[0:2]
注意:创建结果集的过程不涉及任何数据库的操作,查询工作是惰性的,在上面的查询方式中,查询代码不会实际访问数据库,只有查询集在真正使用时,django 才会访问数据库