Django ORM 多对多操做 使用聚合函数和分组 F查询与Q查询

2021年09月15日 阅读数:1
这篇文章主要向大家介绍Django ORM 多对多操做 使用聚合函数和分组 F查询与Q查询,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

建立表

  
# models.py

form django.db import models

class Book(models.Model):  # 表名book,django会自动使用项目名+咱们定义的表名
  # 如没有自定义主键,django会自动添加一个主键,字段名id 自增
  name = models.CharField(max_length=20)  # 字段名name 类型 vachar(20)
  price = models.IntegerField()   # 字段名price 类型int
  pub_date = models.DateField()   # 字段名pub_date 类型 date (时间戳)
  publish = models.ForeighKey('Publish')  # 建立外键关联到Publish表的id字段,django会自动将该名称改成publish_id  
# 若是这样写 publish = models.ForeighKey(Publish) 括号内无引号,则必须将Publish类放到Book类的上面
  authors = models.ManyToManyField('Author',related_name='xxx')  将book与author表作多对多关系 related_name 同一对多中的说明
  # django会自动建立一张表(book与author的中间关联表)名称为appname_book_authors
  def __str__(self):
    return self.name  # 打印实例对象时显示为self.name


#class Book_Author(models.Model):  本身建立第三张表
#  book = models.ForeignKey('book')
#  author = models.ForeignKey('Author')

class Publish(models.Model):
  name = models.CharField(max_length=32)
  city = models.CharField(max_length=32)

class Author(models.Model):
  name = models.CharField(max_length=32)
  age = models.IntegerField()

  def __str__(self):
    return self.name
 
复制代码

多对多的添加设置删除

复制代码
 
# views.py

from django.shortcuts import render
from app_name.models import *  # 导入models.py

def add(request):  # 增长数据的视图函数
  # 系统本身建立的第三张表使用建立对象操做
book_obj = Book.objects.get(id=4)  # 取出id为4的书
  # book_obj.authors.all()  此时取出的是一个空的集合
  authors_obj = Author.objects.all()  # 取出全部author名称的集合
  book_obj.authors.add(*author_obj)  # 将全部做者添加到这本书中
  book_obj.authors.remove(*author_obj) # 将全部做者从书中删除
  book_obj.authors.add(2) # 将id为2的做者添加到此书
  book.obj.authors.add([1,2])  # 将id为1和2的做者添加到此书
  book_obj.authors.remove(1) # 将id为1的做者从书中删除
book_obj.authors.clear() # 清除此书全部的做者
book_obj.authors.set([2,3,4]) # 将书的做者设置为id为2,3,4的做者 (至关于从新设置)
  

# 咱们本身定义的第三张表(不经常使用)
  Book_Author.objects.create(book_id=2, author_id=3)
  
obj = Book.objects.get(id=2)
obj.book_author_set.all()[0]l.author
  

  return HttpResponse('xxx')
复制代码

多对多的查询

复制代码
 
# 怎么使用多对多查询呢?
book_obj = Book.objects.get(name='python')
print(book_obj.name)  # python
print(book_obj.authors.all())  # QuerySet  返回一个QuerySet对象,里面是author的实例集合
print(type(book_obj.authors.all()))  # <class 'django.db.models.query.QuerySet'>

一、查询做者id为2出的全部的书
author_obj=Author.objects.get(id=2)
author_obj.book_set.all()

二、查询三班所对应的全部老师
obj = Classes.objects.filter(name='三班').first()  从班级表取出三班
obj.m.all()  # 从三班中取全部的老师 m表示多对多关系的名称

仍是经过双下划线
二、查询做者alex出的全部书
Book.objects.filter(authors__name='alex').values('name','price')
 
复制代码

使用聚合函数和分组

复制代码
# views.py

from django.db.models import Avg,Min,Sum,Max,Count

# 聚合函数
# 取出全部书总价格的平均值
Book.objects.all().aggregate(Avg('price'))  # 必须使用aggregate函数
# 取alex出的书的总价格
Book.objects.filter(author__name='alex').aggregate(alex_money=Sum('price'))  # {'alex_money':166}
# 取alex出的书的数量
Book.objects.filter(author__name='alex').aggregate(alex_count=Count('price'))  # {'alex_count':2}

# 分组
# 每个做者出的书的总价
Book.objexts.values('author__name').annotate(Sum('price'))  # QuerySet [{'price__sum':211, 'authors__name':'alex'},...]
# 查每一个出版社最便宜书的价格
Publish.bojects.values('name').annotate(Min('book__price'))


复制代码

F查询和Q查询

针对的问题:一、在filter中定义的条件只能是and操做没有or和not   二、若是要将全部书的价格都加上10 用price=price+10是不行的python

复制代码
from django.db.models import Q,F
#第一个问题
Book.objects.filter(Q(price=87)|Q(name='linux'))  # select * from book where (price=87 or name='linux')
Book.objects.filter(~Q(name='linux'))  # select * from book where name != 'linux'
#第二个问题
Book.objects.all().update(price=F('price')+10)

关键字查询与F,Q查询一块儿使用时,必须将F,Q查询放在前面
Book.objects.filter(Q(name='Go'),price=87)