系列文章目录
- Django入门全攻略:从零搭建你的第一个Web项目
- Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作
- Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解
- 还在写0.0…
文章目录
- 系列文章目录
- 前言
- 一、模型类字段
- 1.BooleanField
- 2.CharField
- 3.DateField
- 4.DatetimeField
- 5.DecimalField
- 6.FloatField
- 7.IntegerField
- 二、字段属性
- 1.null
- 2.blank
- 3.choices
- 4.db_column
- 5.db_index
- 6.default
- 7.primary_key
- 8.unique
- 9.verbose_name
- 三、模型类元选项
- 1.abstract
- 2.app_label
- 3.abstract
- 4.db_table
- 5.ordering
- 6.verbose_name
- 7.verbose_name_plural
- 8.ordering
- 四、ORM增删改查
- 0.ORM的增删改查
- 1.增加数据
- 2.查找对象
- 查询中用到的一些字段:
- a.order_by(*field)
- b.count()
- c.order_by(*field)
- d.values(*fields)
- 3.链式过滤条件
- contains:
- icontains:
- range:
- in:
- exact:
- iexact:
- startswith、endswith:
- istartswith、iendswith:
- gte:
- lte:
- 4.修改对象
- 5.删除对象
- 6.ORM的Q、F查询
- Q查询:
- F查询:
- 7.QuerySet
前言
在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 才会访问数据库