Q查询 orm字段补充 查询优化事务操作 图书管理系统
Q查询 orm字段补充 查询优化事务操作 图书管理系统
-
外键字段数据的增删改查
一对多与一对一 publish=对象 publish_id=数字 多对多 add() set() remove() clear()
-
正反向查询的概念
所谓的正反向完全取决于外键字段在谁那儿 """ 正向查询按外键字段 反向查询按表名小写 """
-
基于对象的跨表查询(子查询)
1.先获取一个数据对象 2.其次使用该对象点外键字段或者表名小写(_set.all()) # 1.查询主键为2的书籍对应的出版社 # 分两步看 先查询书籍对象 # book_obj=models.Book.objects.filter(pk=2).first() #书籍对象查出版社对象 (当前在book表 外键字段在这 正向 .外键字段) # res=book_obj.publish # print(res,res.pk,res.name,res.addr) # 5.查询泰罗写过的书籍 # 先查询作者对象 # author_obj=models.Author.objects.filter(name='泰罗').first() #作者对象查询书籍对象 (当前在author对象里,外键字段在书籍对象里 ,所以反向 .表名小写) # res=author_obj.book_set.all() #加了_set 和all # # print(res) # for i in res: # print(i.title)
-
基于双下划綫的跨表查询(连表操作)
"""SQL语句:inner join left join right join union""" 一句orm完成查询操作 # 1.查询主键为2的书籍对应的出版社 #也符合 正向反向查询 目前在book表 外键字段在这 正向 .外键字段 # values('publish'): 目前已经到了出版社这个表 拿什么字段直接__字段名 #返回的是一个列表套字典 # res=models.Book.objects.filter(pk=2).values('publish__name','publish__addr') # print(res) # 5.查询北方出版社出版的书籍 #查出版社对象 出版社对象查询书籍对象 外键不在自己这 反向查询 # res=models.Publish.objects.filter(name='北方出版社').values('book__title') # print(res)
-
双下划綫的进阶操作
在filter方法内直接使用 相同的查询题既可以使用一张表也可以换另外一张表 # 1.查询主键为2的书籍对应的出版社(不能点书籍) # 获取出版社对象数据的.filter方法里面先判断 # 我在出版社这,查找书籍对象 外键字段在书籍对象 反向查询 .表名小写__查询的条件 # res = models.Publish.objects.filter(book__pk=2) # print(res) #获取的是列表套数据对象<QuerySet [<Publish: 这是对象:东方出版社>]> # # res = models.Publish.objects.filter(book__pk=2).first() # print(res.name) #东方出版社 # 5.查询北方出版社出版的书籍 # 创建书籍表对象 书籍表查询出版社对象 外键字段在自己这 正向查询.外建名字 # res=models.Book.objects.filter(publish__name='北方出版社') # #返回的是列表套数据对象 # print(res) #<QuerySet [<Book: 这是对象:活着>, <Book: 这是对象:我在精神病院学斩神>]> # # for i in res: #先循环出来数据对象 在点字段名 # print(i.title) #活着 我在精神病院学斩神
-
聚合查询
from django.db.models import Max,Min,Count,Sum,Avg models.Book.objects.aggregate() # 3.统计价格最高的 # res=models.Book.objects.aggregate(Max('price')) # print(res)
-
分组查询
"""SQL语句:group by""" models.Book.objects.annotate() # 按照models后面的表数据主键分组 models.Book.objects.values('price').annotate() # 指定分组的依据 # 4.查询各个作者出的书的总价格 #每个 以作者分组 #作者对象 查找书籍对象 反向查询 # res= models.Author.objects.annotate(sum_price=Sum('book__price')).values('sum_price','name') # print(res) """ 1.大的分组 models.表名.objects.annotate 按照models后面的表名分组(主键) 2.小的分组 models.表名.objects.values('price').annotate() 按照values括号内指定的字段分组 """
-
F查询
"""F查询能够帮助我们获取到表中指定字段对应的原始数据""" from django.db.models import F # 1.将所有书籍的价格提升100块 #使用F # models.Book.objects.update(price=F('price')+100) # 2.将所有书籍名称后面加上爆款后缀 # 一般F用来操作数据对象 这个不常用 # from django.db.models.functions import Concat # from django.db.models import Value # models.Book.objects.update(title=Concat(F('title'), Value('爆款'))) # 3.查询库存数大于卖出数的书籍 # res=models.Book.objects.filter(kucun__gt=F('maichu')) # print(res) # for i in res: # print(i.title)
- Q查询
- orm字段相关补充
- orm查询优化相关
- orm事务操作
- 图书管理系统练习
Q查询
"""Q查询"""
# filter括号内多个条件默认逗号分隔 均为and关系
# 1.查询主键为3或者卖出数为1000的数据
# res = models.Book.objects.filter(pk=3, maichu=1000) # 逗号分隔为and关系
from django.db.models import Q
###########基本用法###########
# res = models.Book.objects.filter(Q(pk=3), Q(maichu=1000)) # 逗号分隔为and关系
# res = models.Book.objects.filter(Q(pk=3) | Q(maichu=1000)) # |分隔为or关系
# res = models.Book.objects.filter(~Q(pk=3) | Q(maichu=1000)) # ~分隔为not关系
# print(res)
###########进阶用法###########
# filter(title='123') filter('title'='123')
q = Q() # 默认多个条件之间也是and关系
q.connector = 'or' # 也可以修改链接关系
# q.children.append(('title', '三国演义爆款'))
q.children.append(('title__contains', '爆'))
q.children.append(('price', 1123))
res = models.Book.objects.filter(q)
print(res)
orm事务操作
"""
事务:ACID
A原子性 每个事务都是不可分隔的最小耽误,要么同时成功,要么同时失败
C一致性 执行完事务之后,数据库数据的状态从一个一致性状态变为另一个一致性状态(一致性与原子性是密切相关的)
I独立性 事务与事务之间彼此独立 互不干扰
D持久性 一个事务提交之后 他对数据的操作是永久的
start transaction 开启事务
...
rollback 回滚
commit 确认
"""
from django.db import transaction
# 事务
# 买一本 跟jason学Linux 书
# 在数据库层面要做的事儿
# 1. 创建一条订单数据
# 2. 去产品表 将卖出数+1, 库存数-1
from django.db.models import F
# 开启事务处理
try:
with transaction.atomic():
# 创建一条订单数据
models.Book.objects.create(num="110110111", product_id=1, count=1)
# 能执行成功
models.Book.objects.filter(id=1).update(kucun=F("kucun") - 1, maichu=F("maichu") + 1)
except Exception as e:
print(e)
transaction.rollback() # 回滚
transaction.commit() # 提交
orm常用字段
# verbose_name 中文标识
AutoField() # 专门用于主键
"""需要指定primary key参数"""
CharField()
"""需要指定max_length参数 varchar()"""
IntegerField()
DecimalField()
DateField()
DateTimeField()
"""
auto_now 每次更新数据记录的时候会更新该字段
auto_now_add 创建数据记录的时候会把当前时间添加到数据库
"""
BooleanField() # 布尔值类型
"""
传布尔值 存0或1
is_delete = models.BooleanField()
is_alive = models.BooleanField()
is_buy = models.BooleanField()
"""
TextField() # 文本类型
"""
专门用于存储大段文本数据
比如文章内容...
"""
EmailField() # 邮箱类型
FileField()
- 字符串,路径保存在数据库,文件上传到指定目录
- upload_to = "" 上传文件的保存路径
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
"""自定义字段:为了防止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
# 重要参数
null = True
default = None
unique 如果设置为unique=True 则该字段在此表中必须是唯一的 。
db_index 如果db_index=True 则代表着为此字段设置索引。
# 外键字段
to、to_field、on_delete、related_name(给外键字段起别名 用于正反向)
db_constraint
django1.x 2.x以上版本外键区别
django1.x是级联更新,级联删除
django2.x以上需要手动同步on_delete=CASCADE
orm查询优化
only与defer
select_related与prefetch_related
"""1.在ORM语句中 默认所有的查询都是惰性查询"""
# res = models.Book.objects.all()
# res1 = models.Book.objects.filter(pk=1)
"""2.only与defer"""
# 获取指定字段对应的数据 并且封装成字典
# res = models.Book.objects.values('title')
# for d in res:
# print(d,type(d))
# print(d.get('title'))
# 获取指定字段对应的数据 并且封装成对象
# res = models.Book.objects.only('title')
# for obj in res:
# print(obj.title)
# print(obj.price)
# print(obj.publish_time)
"""
对象点击only括号内填写的字段名称不会再走数据库查询
但是点击括号内不存在的字段名称则每次都会走数据库查询
"""
# res = models.Book.objects.defer('title')
# for obj in res:
# print(obj.price)
"""
与only互为反操作
"""
# res = models.Book.objects.filter(pk=3).first()
# print(res.publish.name)
"""select_related括号内只能放外键字段 并且不支持多对多外键字段"""
# res = models.Book.objects.select_related('publish')
# for obj in res:
# print(obj.publish.name)
"""
内部是连表操作 会将外键关联的表与当前表拼接 之后将所有的数据全部封装到数据对象中 一条sql
之后对象无论查询哪个表的数据都不再走数据库查询
"""
res = models.Book.objects.prefetch_related('publish')
for obj in res:
print(obj.publish.name)
"""
内部是子查询操作 先查询所有的书籍数据 之后查询每本书籍数据对应的出版社数据 两条sql
之后将总数据封装到数据对象中
"""
图书管理系统
功能:只需要实现图书的增删改查即可
界面:使用bootstrap框架
知识点:路由层 视图层 模板层 模型层全部
1.先创建数据库db321
2.新建项目 创建数据表 添加数据