Q查询进阶操作

from django.db.models import Q
q_obj = Q() # 1.产生q对象
q_obj.connector = 'or' # 默认多个条件的连接是and可以修改为or
q_obj.children.append(('pk', 1)) # 2.添加查询条件
q_obj.children.append(('price__gt', 2000)) # 支持添加多个
res = models.Book.objects.filter(q_obj) # 查询支持直接填写q对象
print(res)

如下图查询条件的左边到底是什么?



pk 和 'pk'是有很大区别的!

pk是一个变量,或者说是一个关键字实参。

'pk'是一个字符串。

使用Q查询可以通过输入字符串来控制如何查询。

首先Q查询,其实使用的是Q类产生的对象:



产生Q对象:



Q对象里面可以存放查询条件。

children.append

使用Q对象.children.append方法可以往Q对象里面添加多个查询条件。

查询条件添加好之后,直接将Q对象放入filter:

使用append添加查询条件,条件之间默认是and关系。

也可以修改成or关系:

使用q_obj.connector = 'or'

图书查询功能

把查询条件变成字符串,意味着可以与用户互动。

用户的输入就是字符串,获取到用户输入的字符串,就可以从数据库拿到数据。

需求:利用q查询进阶操作编写一个简易版本的图书查询功能。

ORM查询优化

惰性查询

看如下例子:



为什么日志不打印??

orm的查询默认都是惰性查询。什么叫惰性查询?

因为查询的结果res没有用到,所以orm干脆不执行,可以减轻一点数据库的负担。

自动分页 limit

举例:我们的表里面有几亿条数据!然后使用orm进行查询。

orm的查询自带分页处理:



orm底层写的sql使用了LIMIT关键字,这里就是直接限制展示的条数为21.

only与defer

	'''数据对象+含有指定字段对应的数据'''
# res = models.Book.objects.only('title', 'price')
# print(res) # queryset [数据对象、数据对象]
# for obj in res:
# print(obj.title) # 点击括号内填写的字段 不走SQL查询
# print(obj.price)
# print(obj.publish_time) # 可以点击括号内没有的字段获取数据 但是会走SQL查询 res = models.Book.objects.defer('title', 'price')
# print(res) # queryset [数据对象、数据对象]
for obj in res:
# print(obj.title) # 点击括号内填写的字段 走SQL查询
# print(obj.price)
print(obj.publish_time) # 点击括号内没有的字段获取数据 不走SQL查询

请看如下例子:

all方法可以拿到所有的书籍对象,数据全在对象里。通过values方法可以拿到书籍的name字段、price字段。name、price存在一个queryset结果集里,格式是列表套字典。并且这个字典是无法使用点的方式取值的。

only



得到的结果变成列表套数据对象(此时是书籍对象)。

此时我们就可以通过点的方式取值:



同时这个only产生的书籍对象,还可以点only括号内没有的字段:



点这个不存在的字段时,only产生的对象肯定也没有相应的数据。此时该对象就会使用sql对数据库进行查询获得数据。并且每次点这个不存在的字段时都会查一次数据库。

defer



defer和only相反,defer括号里没有的字段会在第一次SQL查询后封装到对象中。

如这里obj.publish_time是一个括号中没出现的字段,这种字段的数据会封装到BOOK对象中。反而是出现在括号内的字段,需要额外的sql来进行数据的查询。

总结:对象中有的数据,就不会再执行SQL进行查询,因为这会增加数据库的负担。当对象想使用自己内部没有的数据时,就会调用SQL语句进行查询。

select_related与prefetch_related

select_related与prefetch_related里面都只能填写一对多、一对一外键字段,不支持多对多外键。

	 # res = models.Book.objects.all()
# for obj in res:
# print(obj.publish.name) # 每次查询都需要走SQL
# res = models.Book.objects.select_related('authors') # 先连表后查询封装
# res1 = models.Author.objects.select_related('author_detail') # 括号内不支持多对多字段 其他两个都可以
# print(res1)
# for obj in res:
# print(obj.publish.name) # 不再走SQL查询 res = models.Book.objects.prefetch_related('publish') # 子查询
for obj in res:
print(obj.publish.name)

select_related

示例:



数据对象点出版社的字段name 出版社的名字肯定不会封装在book对象 所以就需要临时写SQL去数据库查询

但是这样会写很多SQL,增加数据库负担。

不想走SQL,意味着要在第一句SQL里全部查询到。

这时候就要使用select_related:



底层是帮你把书籍表和出版社表进行连表操作。

这样就后续调用就不需要走sql了:因为数据都封装到对象了。

prefetch_related



prefetch_related的底层是子查询。

先查一张表再查另外一张表,最后把数据封装到对象。

ORM事务操作

事务复习

"""
1.事务的四大特性(ACID)
原子性、一致性、隔离性、持久性
2.相关SQL关键字
start transaction;
rollback;
commit;
savepoint;
3.相关重要概念
脏读、幻读、不可重复读、MVCC多版本控制...
"""

django orm提供了至少三种开启事务的方式

方式1: 全局有效 配置文件数据库相关添加键值对

       "ATOMIC_REQUESTS": True每次请求所涉及到的orm操作同属于一个事务



默认每一次网络请求,涉及到的所有orm操作同属于一个事务。如果哪个orm报错了,事务会自动回滚。

比如:



对于这次请求,只要程序执行到了return,事务就算已经执行成功了。也就是说return后面报错了,数据库也还是会新增数据。

如果不配置django事务,默认情况下是没有事务的,代码走到哪里就是哪。可能出现前几个orm成功,后几个orm失败的情况。

方式2: 局部有效 装饰器

       from django.db import transaction
@transaction.atomic
def index():pass

这个是局部开启:

用装饰器装饰视图函数,这个视图函数内部就属于一个事务。只要函数内报错,事务就会回滚。数据库会恢复到进行事务之前的状态。



极限情况:(return后面必须返回httprespon对象)

方式3: 局部有效 with上下文管理

       from django.db import transaction
def reg():
with transaction.atomic():
pass

with的子代码内是一个事务:(这种方式用于更小的局部,只能在某个代码块)



示例:

ORM常用字段类型

AutoField
primary_key=True
CharField
max_length
IntegerField
BigIntergerField
DecimalField
max_digits decimal_places
DateField
auto_now auto_now_add
DateTimeField
auto_now auto_now_add

BooleanField

传布尔值自动存0或1

TextField

存储大段文本

有个数限制的使用CharField(用户名)。

个数不固定的使用TextField(小说)。

EmailField

存储邮箱格式数据

FileField

传文件对象 自动保存到提前配置好的路径下并存储该路径信息

主库保存的是文件路径!其他数据库里保存具体的文件数据。

自定义字段

比如django orm中没有专门的char字段。Charfield实际是数据库中的varchar。

orm给我们提供的字段并不是没有使用到char字段的:

'UUIDField':'char(32)'

'IPAddressField':'char(15)'

但是你用这些字段去完成别的事,不符合变量名的见名知义。

所以,我们可以通过自定义字段类型的方式,定义出char字段:

class MyCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super().__init__(max_length=max_length, *args, **kwargs) def db_type(self, connection):
return 'char(%s)' % self.max_length

如下图,orm这些字段都继承于父类Field:



重写字段类:



使用自定义字段:

更多orm字段

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)
- 二进制类型

ORM字段与MySQL字段对应关系


'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',

ORM常用字段参数

primary_key 	主键
verbose_name 注释
max_length 字段长度
max_digits 小数总共多少位
decimal_places 小数点后面的位数
auto_now 每次操作数据自动更新事件
auto_now_add 首次创建自动更新事件后续不自动更新
null 允许字段为空
default 字段默认值
unique 唯一值
db_index 给字段添加索引
choices 当某个字段的可能性能够被列举完全的情况下使用
性别、学历、工作状态、...
class User(models.Model):
name = models.CharField(max_length=32)
info = MyCharField(max_length=64)
# 提前列举好对应关系
gender_choice = (
(1, '男性'),
(2, '女性'),
(3, '其他'),
)
gender = models.IntegerField(choices=gender_choice,null=True)
user_obj = User.objects.filter(pk=1).first()
user_obj.gender
user_obj.get_gender_display() to 关联表
to_field 关联字段(不写默认关联数据主键)

on_delete

on_delete		当删除关联表中的数据时,当前表与其关联的行的行为。
1、models.CASCADE
级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似

choices参数(重点)

当某个字段的可能性能够被列举完全的情况下使用

比如:性别 学历 工作状态

先在类中写好对应关系:



然后gender这个字段就可以用整数类型存:



默认值的设置:

display

可以通过对应关系获取整数对应的字符串:



如这里pk=1的user_obj里gender字段为1,数字一对应的是男性,就可以通过display获取。

如果没有对应关系:



display方法就会返回数据库中存储的值

示例1:



使用这种方式,可以节省数据库空间,用更小的字段存储数据。

示例2:工作经验



示例3:生源由来

总结:相当于在对象中存储了更多的数据。

Q查询进阶操作 ORM查询优化 only与defer select_related与prefetch_related ORM事务 ORM常用字段类型 ORM常用字段参数的更多相关文章

  1. ORM数据库查询优化only与defer(select_related与prefetch_related)

    目录 一:数据库查询优化 1.ORM语句特点 2.only 3.defer 4.only与defer区别 5.select_related与prefetch_related 6.select_rela ...

  2. 12月19日内容总结——Q查询进阶、ORM查询优化、ORM事务、ORM常用字段类型和字段参数、Ajax介绍、数据编码格式、Ajax携带文件数据

    目录 一.Q查询进阶操作 二.ORM查询优化 三.ORM事务操作 四.ORM常用字段类型 五.ORM常用字段参数 六.Ajax AJAX简介 应用场景 AJAX的优点 语法实现 七.数据编码格式(Co ...

  3. Django框架之第八篇(模型层补充)--数据库的查询与优化:only/defer,select_related与prefetch_related,事务

    在设置外键字段时需要注意: 当你使用django2.x的版本时候,在建立外键关系时,需要你手动添加几个关键点参数 models.cascade #设置级联删除 db_constraints 数据库查询 ...

  4. day09 orm查询优化相关

    day09 orm查询优化相关 今日内容概要 orm字段相关补充 orm查询优化相关 orm事务操作 图书管理系统练习 今日内容详细 orm事务操作 """ 事务:ACI ...

  5. Django框架:8、聚合查询、分组查询、F与Q查询、ORM查询优化、ORM事务操作、ORM常用字段类型、ORM常用字段参数

    Django 数据库 目录 Django 数据库 一.聚合查询 二.分组查询 三.F查询与Q查询 1.F查询 2.Q查询 3.Q查询进阶操作 四.ORM查询优化 1.only与defer 五.ORM事 ...

  6. 聚合查询、分组查询、ORM中如何给表再次添加新的字段、F与Q查询、ORM查询优化、ORM事务操作、ORM常用字段类型、ORM常用字段参数、Ajax、数据编码格式(Content-Type)、ajax携带文件数据

    今日内容 聚合查询 在ORM中支持单独使用聚合函数,需要使用aggregate方法. 聚合函数:Max最大.Min最小.Sum总和.Avg平均.count统计 from django.db.model ...

  7. (补12月19)ORM查询优化、ORM事物操作、ORM常用字段参数、Ajax请求、Content-Type

    ORM查询优化.ORM事物操作.ORM常用字段参数.Ajax请求.Content-Type Q查询进阶操作 先产生一个对象 q_obj = Q() 修改默认对象 q_obj.connector = ' ...

  8. Django之F、Q查询,事务,自定义char字段

    F查询 from django.db.models import F,Q # 当查询条件来自于数据库的某个字段,这个时候就必须使用F # 查询卖出数大于库存数的商品 res = models.Prod ...

  9. 第五章、Django之多表查询进阶与事务

    目录 第五章.Django之多表查询 一.聚合查询 二.分组查询 三.F与Q查询 四.查询优化 五.Django开启事务 六.自定义char字段 七.ORM常用字段 第五章.Django之多表查询 一 ...

  10. 聚合与分组查询,F与Q查询

    from django.db.models import Q 查询书籍名称是python入门或者价是555.55的书 book_queryset = models.Book.objects.filte ...

随机推荐

  1. AdaBoost算法解密:从基础到应用的全面解析

    本文全面而深入地探讨了AdaBoost算法,从其基础概念和原理到Python实战应用.文章不仅详细解析了AdaBoost的优缺点,还通过实例展示了如何在Python中实现该算法. 关注TechLead ...

  2. Vue05-Vuex

    01. 什么是状态管理 在开发中,我们的应用程序需要处理各种各样的数据,这些数据需要保存在我们应用程序的某一个位置,对于这些数据的管理我们就称之为 状态管理. 在Vue开发中,我们使用组件化的开发方式 ...

  3. 【结对作业】第一周 | 学习体会day06

    初步做了app的页面 change作为mysql的关键字,不可以作为命名,否则报错 做了两条线路的中转 初步学习了frame标签,打算明天实现页面的部分切换

  4. 在模态窗口中控制窗口的隐藏和显示(.NET)

    如果你创建了模态窗口,虽然一些API,例如Editor.GetSelection(),可以自动隐藏模式对话框,但如果从模态窗口出发与编辑器(编辑器指的模型空间,即你绘图的窗口)交互, 它会在GetSe ...

  5. Linux下通过AnySetup配置防火墙

    软件 AnySetup 主要功能 主要功能是对Linux操作系统下的基本配置进行管理.多种服务配置进行管理.安全配置进行管理等.如:操作系统的升级管理,软件包的安装.更新和卸载管理,软件仓库源的管理, ...

  6. ABAP 泰国凭证批导 报错 F51 192 输入一个业务场景

    泰国凭证批导报错 F51 192 输入一个业务场景 方案一: 方案二:  ID_BUPLA  用户参数

  7. Java的四种内部类(成员内部变量,静态内部变量,局部内部类,匿名内部类)

    内部类 内部类就是在一个内的内部再定义一个内 内部类的分类:成员内部类,静态内部类,局部内部类,匿名内部类 (1)成员内部类 指类中的一个普通成员,可以定义成员属性,成员方法 内部类是可以访问外部类的 ...

  8. 配置tabBar导航菜单与open跳转差异

    "tabBar": {        "color": "#333",        "selectedColor": ...

  9. C# 提取PDF中指定文本、图片的坐标

    获取PDF文件中文字或图片的坐标可以实现精确定位,这对于快速提取指定区域的元素,以及在PDF中添加注释.标记或自动盖章等操作非常有用.本文将详解如何使用国产PDF库通过C# 提取PDF中指定文本或图片 ...

  10. 介绍一款轻量型 Web SCADA 组态软件

    ​ 随着互联网.物联网技术的快速发展,图扑物联基于多年研发积累和私有部署实践打磨.以及对业务场景的深入理解,推出了适用于物联网应用场景的轻量型云组态软件. 该产品采用 B/S 架构,提供 Web 管理 ...