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
posted @ 2019-07-10 09:02  言值  阅读(183)  评论(0编辑  收藏  举报