ORM之多表操作
链接地址 : https://www.cnblogs.com/maple-shaw/articles/9403501.html
ForeignKey操作
基于对象的查询 (跨表)
# 正向查询: 拥有外键 多--> 一
book_obj = models.Book.objects.get(pk=3)
print(book_obj.publisher) # 关联的对象
print(book_obj.publisher_id) # 关联对象的id
# 反向查询 : 一 --> 多
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.book_set) # RelatedManager: 管理对象
# 不指定related_name, 反向查询为关联的表名小写: obj.表名_set
ret = pub_obj.book_set.all()
# 指定related_name='books', 基于对象的反向查询
ret = pub_obj.books.all()
基于字段的查询
ret = models.Book.objects.filter(publisher__name='春秋出版社')
# 不指定related_name : 表名__字段
ret = models.Publisher.objects.filter(book__title='春')
# 指定related_name = 'books' 基于对象查询
ret = models.Publisher.objects.filter(books__title='春')
# 指定related_query_name='book' 基于字段查询 (反向查询)
ret = models.Publisher.objects.filter(book__title='春')
ManyToManyField操作
基于对象的查询
# 正向查询
author_obj = models.Author.objects.get(pk=1)
ret = author_obj.books.all()
# 反向查询 (可指定related_name)
book_obj = models.Book.objects.get(pk=1)
ret = book_obj.author_set.all()
管理对象的方法
book_obj = models.Book.objects.get(pk=1) # 反向
author_obj = models.Author.objects.get(pk=2) # 正向
创建的方法
1. set(): 更新model对象的关联对象。(外键只能添加对象)
# 设置多对多关系
author_obj.books.set([2,4]) # 可迭代对象 或者对象
author_obj.books.set(models.Book.objects.filter(id__in=[1,3]))
book_obj.author_set.set([3]) # 反向设置多对多关系
2. add(): 把指定的model对象添加到关联对象集中。
# 添加对象 或者id (多对多关系)
author_obj.books.add(1,2)
author_obj.books.add(models.Book.objects.get(pk=4))
3. create()
# 创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。
author_obj.books.create(title='春',publisher_id=1) # 正向
book_obj.author_set.create(name='xxx') # 反向
4. update() 更新,与save()不同, 只设置指定字段
models.Book.objects.filter(pk=1).update(price=999.99)
删除的方法
1. remove(): 从关联对象集中移除执行的model对象
# 删除多对多关系
author_obj.books.remove(1,2)
author_obj.books.remove(models.Book.objects.get(pk=4))
2. clear(): 从关联对象集中移除一切对象。
# 清空对应的所有多对多关系
author_obj.books.clear()
# 注意: 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
聚合和分组
聚合
aggregate()
是QuerySet
的一个终止子句,它返回一个包含一些键值对的字典。
键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。
# 内置函数
from django.db.models import Avg, Sum, Max, Min, Count
简单的查询
1.查找书的价格的最大值
ret = models.Book.objects.all().aggregate(max=Max('price'),min=Min('price'))
# 字典 {'price__max': Decimal('998.00')} 注意: 改名字都改 要不就不改
2.该出版社的书的最大最小价格
ret = models.Book.objects.filter(publisher__name='战国出版社').aggregate(max=Max('price'), min=Min('price'))
分组
1. 统计一本书的作者个数 annotate: 注释
ret = models.Book.objects.annotate(Count('author')).values() # QuerySet
2. 统计出每个出版社买的最便宜的书的价格
# 通过出版社的对象查询
ret = models.Publisher.objects.annotate(Min('book__price')).values()
# 通过书的对象查询
ret = models.Book.objects.values('publisher').annotate(Min('price'))
ret = models.Book.objects.values('publisher__name').annotate(Min('price'))
ret=models.Book.objects.values('publisher').annotate(min=Min('price')).values('publisher__name','min' )
# 后面的values中不能添加额外字段, 会拿额外的字段作为分组的条件
# 查找不止一个作者的图书
ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
# 根据一本图书作者数量的多少对查询集 QuerySet进行排序
ret = models.Book.objects.annotate(count=Count('author')).order_by('-count')
# ' - ' 代表降序排序
# 查询各个作者出的书的总价格
ret = models.Author.objects.annotate(Sum('books__price')).values()
F查询和Q查询
F查询
from django.db.models import F
1.F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
# 销量大于库存
ret = models.Book.objects.filter(sale__gt=F('inventory')).values()
2.Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)
3.修改操作也可以使用F函数
# 将销量的翻倍, update做局部更新操作
models.Book.objects.all().update(sale=F('sale')*2)
Q查询
from django.db.models import Q
1.组合 & 和 | 操作符以及使用括号进行分组来编写复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。
models.Book.objects.filter(~(Q(id__gt=2) & Q(id__lt=6)) | Q(id__lt=3))
2.查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
models.Book.objects.filter(Q(p_date__year=2018) | Q(p_date__year=2017), title__icontains="物语")
# filter() 等方法中的关键字参数查询都是一起进行“AND” 的。
事务
from django.db import transaction
try:
with transaction.atomic():
models.Publisher.objects.create(name='春秋出版社')
except Exception as e:
print(e)
# 防止事务的回滚, 进行try防止报错
Django终端打印SQL语句
# setting.py中配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
在Python脚本中调用Django环境
# 在py文件中执行orm操作的语句
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "practice.settings")
import django
django.setup()
from app01 import models