ORM(下)
内容概要
- Q查询进阶操作
- ORM查询优化
- ORM事务操作
- ORM常用字段类型
- ORM常用字段参数
- ORM三种创建多对多方式
Q查询进阶操作
"""
Q查询的进阶操作
"""
from django.db.models import Q
# 先产生Q对象
q_obj = Q()
# 确认条件之间的连接关系
q_obj.connector = 'or' # 以 or连接
# 添加条件 pk=1
q_obj.children.append(('pk', 1))
# 在添加 一个 条件 name= '西游记'
q_obj.children.append(('name', '西游记'))
# 现在相当于 pk=1 or name='西游记'
res = models.Book.objects.filter(q_obj)
res1 = models.Book.objects.filter(Q(pk=1) | Q(name='西游记'))
print(res)
print(res1)

ORM查询优化
-
ORM查询默认都是惰性查询
就是如果你这行代码后续没有用到 那么我就不会执行
-
ORM查询自带分页

-
only"""数据对象 + 含有指定字段对应的数据"""
一条SQL

还是一条SQL
但是在点一个
only括号外的数据的时候res = models.Book.objects.only('name', 'price') for obj in res: print(obj.register_time)
每一次循环都会产生一条
SQL语句总结:如果是
only括号内的字段不走SQL,括号外的走SQL -
deferres = models.Book.objects.defer('name', 'price') for obj in res: print(obj.name)
res = models.Book.objects.defer('name', 'price') for obj in res: print(obj.register_time)
总结:
defer在查询括号内的字段的时候做走SQL,括号外的不走SQL -
select_relatedres = models.Book.objects.select_related('publish') print(res)
-
prefetch_relatedres = models.Book.objects.prefetch_related('publish') print(res)
总结:select_related是连表操作,perfetch_related是子查询
ORM事务操作
-
事务的四大特性(ACID)
原子性、一致性、隔离性、持久性
-
相关SQL关键字
""" start transaction; 启动事务 rollback; 回滚 commint; 确认 直接刷进内存了 savepoint; # 保存点 """ -
相关重要概念
脏读、幻读、不可重复读、MVCC多版本控制.... -
django orm提供了至少三种开启事务的方式
全局有效
方式一:配置文件数据库添加相关键值对 全局有效
"ATOMIC_REQUESTS": True 每次请求所涉及到的ORM操作属于同一个事物
然后再视图函数里面写ORM的操作,如果遇到报错则回滚,返回的不是一个
HttpResponse对象的报错不算def index_func(request): models.Book.objects.create(name='石头记', price='19.9', publish_id=1) paa return HttpResponse('嘿嘿')执行之前

执行后

因为在执行的过程中报错了,所以事务回滚到执行前了所以没有添加进去。
def index_func(request): models.Book.objects.create(name='石头记', price='19.9', publish_id=1) return HttpResponse('嘿嘿')
这样就添加进去,虽然事务回滚了,但是主键记录了,它是添加过数据的。
def index_func(request): models.Book.objects.create(name='射雕英雄传', price='19.9', publish_id=1) return 111返回的不是一个
HttpResponse对象 的报错不影响事务,
也是添加成功的
-
方式二:装饰器 局部有效
from django.db import transaction @transaction.atomic def index():pass -
方式三:
with上下文管理 局部有效from django.db import transaction def reg(): with transaction.atomic(): pass
-
ORM常用字段
-
AutoFieldint自增列,必须要填入参数
primary_key=True。如果model中没有自增列,则会自动创建一个列名为id的列 -
IntegerField一个整数类型,范围在
-2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存)
-
CharField
字符串类型,必须提供
max_length参数,max_length表示字符长度。这里需要直到的是Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段,但是Django允许我们自定义新的字段自定义字段写法
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应用
class UserInfo(models.Model): name = MyCharField(max_length=32) phone = models.CharField(max_length=32)
-
DateField日期字段,日期格式
YYYY-MMM-DD,相当于Python中的datetime.date()实例。 -
DateTimeField日期时间字段,相当于Python的
datetime.datetime()实例 -
BigIntegerFieldMySQL的bigint -
SmallIntegerFieldMySQL的samllint -
BooleanField传布尔值自动存0或1
-
TextField存储大段文本
-
EmailField存储邮箱格式数据
-
FileField传文件对象 自动保存到提前配置好的路径下并存储该路径信息
ORM常用字段参数
primary_key 主键
verbose_name 注释
max_length 字段长度
max_digits 数值的总长度
decimal_places 小数点后面的位数
auto_now 每次操作数据自动更新时间
auto_now_add 首次创建数据的时间
null 允许字段为空
default 字段默认值
unique 唯一值
db_index 给字段添加索引
choices 当某个字段的可能性能够完全列举出来出来的情况下使用
比如:性别、学历、工作状态...
实操
class UserInfo(models.Model):
name = MyCharField(max_length=32)
phone = models.CharField(max_length=32)
# 列举好对应关系
gender_choice = (
(1, '男'),
(2, '女'),
(3, '其他')
)
gender = models.IntegerField(choices=gender_choice, verbose_name='性别', default=1)
取出来
# res = models.UserInfo.objects.create(name='jason', phone=140, gender=1)
res = models.UserInfo.objects.filter(name='jason').first()
print(res.gender)
print(res.get_gender_display())

to 关联表
to_field 关联字段(不写默认关联数据主键)
on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。
-
models.CASCADE级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时删除
-
models.SET_NULL级联操作,当主表中被连接的一条数据删除时,从表中所有与之相关联的数据的相关字段设置为
null,此时注意外键时,这个字段必须可以为空 -
models.PROTECT当主表中的一行数据删除时,由于从表中相关字段时受保护的外键,所以都不允许删除
-
models.SET_DEFAULT当主表的一行数据删除时,从表中所有相关数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
-
models.SET()当主表中的一条数据删除时,从表所有的关联数据字段设置为SET()中设置的值,与
models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数 -
models.DO_NOTHING什么都不做,一切都看数据库级别的约束,
注:数据库级别的默认约束为
RESTRICT,这个约束与django中的models.PROTECT相似
多对多三种创建方式
-
全自动创建
class Book(models.Model): title = models.CharField(max_length=32, verbose_name='书名') authors = models.ManyToManyField(to='Author') class Author(models.Model): name = models.CharField(max_length=32, verbose_name='姓名')优势:自动创建第三张表, 并且提供了add、remove、set、clear以及正反向概念
劣势第三张表无法创建更多的字段 扩展性较差
-
全手动
class Book(models.Model): title = models.CharField(max_length=32, verbose_name='书名') class Author(models.Model): name = models.CharField(max_length=32, verbose_name='姓名') class Book2Author(models.Field): book = models.ForeignKey(to=Book, on_delete=models.CASCADE) author = models.ForeignKey(to=Author, on_delete=models.CASCADE) others = models.CharField(max_length=32, verbose_name='其他') join_time = models.DateField(auto_now_add=True, verbose_name='绑定时间')优势:第三张表完全由自己创建,扩展性强
劣势:编写繁琐 并且不在支持add、remove、set、clear以及正方向概念
-
半自动
class Book1(models.Model): title = models.CharField(max_length=32) authors = models.ManyToManyField(to='Author1', through='Book1ToAuthor1', through_fields=('book', 'author')) # 在哪个表就先填那个字段 class Author1(models.Model): name = models.CharField(max_length=32) class Book1ToAuthor1(models.Model): book = models.ForeignKey(to=Book1, on_delete=models.CASCADE) author = models.ForeignKey(to=Author1, on_delete=models.CASCADE) join_time = models.DateField(auto_now_add=True)优势:第三张表完全由自己创建 扩展性强 正反向概念依然可见
劣势:编写繁琐 不在支持 add、set、remove、clear

浙公网安备 33010602011771号