碎片一:Django的JsonResponse
我们在写django时在views需要定义返回json格式的数据给前端的视图函数,这个时候可以用上JsonResponse,它是Django自带的处理json格式数据的资源
1、配置urls
2、编写视图函数
3、访问响应地址,就能看到返回的数据是json数据(JsonResponse将我们的datadict数据自定转成了json格式)
注意:下面介绍如何使用JsonResponse返回列表数据,只需要在JsonResponse的参数将safe设置为false即可,不检查是否是字典格式
碎片二:外键的正向查询与反向查询
1、正向查找与反向查找的含义
#出版社
class Publisher(models.Model):
'''出版社数据表'''
id=models.AutoField(primary_key=True) #自增ID主键
name=models.CharField(max_length=50,verbose_name='出版社名称',null=False,unique=True)
addr=models.CharField(max_length=128,verbose_name='出版社地址',default='成都市动物园')
def __str__(self):
return '{},{}'.format(self.id,self.name,self.addr)
#书
class Book(models.Model):
'''书数据表'''
id=models.AutoField(primary_key=True)
title=models.CharField(max_length=50,verbose_name='书名',null=False,unique=True)
publisher=models.ForeignKey(to="Publisher")
def __str__(self):
return '{},{},{}'.format(self.id,self.title,self.publisher)
如上图可以看到,在Book字段中设置了外键publisher关联到表Publisher,如果从Book到Publisher进行查找,那么就是正向查找,如果是Publisher到Book进行查找,那么就是反向查找
2、正向查询与反向查询的具体代码操作
基于对象的正向查询:通过book表外键获取到publisher对象,然后去查询到Publisher表中对应对象的相关字段值
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#外键查询操作-正向查询
book_obj=Book.objects.all().first()
#获取到外键关联的对象
get_pub=book_obj.publisher
#获取外键对象的属性
print(get_pub.id) #id
print(get_pub.name) #name
print(get_pub.addr) #addr
基于双下划线的正向查询:跨表查询(查询出来是一个对象信息,双下划线就表示跨了一张表),book表中有一个publisher外键字段,通过双下划线表示跨到外键对应表中查询name字段
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#外键查询操作-跨表查询
#查询id是1的出版社的名称
get_pubname=Book.objects.filter(id=1).values('publisher__name')
print(get_pubname)
基于对象的反向查询:
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#反向操作
#查询出第一个出版社
get_publisher=Publisher.objects.all().first()
#反向查询对应的书籍有哪些,反向查询的表_set就是反向查询
get_books=get_publisher.book_set.all()
print(get_books)
注意:
1、反向查询首先是获取的一个外键指定表publisher的对象get_publisher,然后通过book表进行反向查询对应的书籍,就是利用book_set进行反向查询
2、如果在book表中设置了related_name,那么book_set需要写成related_name的名称
利用双下划线的反向查询:
利用双下划线进行反向查询的话,那么我们需要在外键的表中设定related_name
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
# 反向操作-双下划线,必须要先设置related_name
get_book_title=Publisher.objects.filter(id=1).values('books__title')
print(get_book_title)
注意:外键补充说明,在使用orm时需要确定是具体的对象还是queryset,针对不同的情况使用不同的函数
碎片三:多对多查询
多对多表在django当中是以manytomany进行关系确立的,下面介绍多对多表相关操作
1、查询:查询某一个作者所编写的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#多对多
#1、查询id为1的作者写的书籍
author_obj=Author.objects.all().first() #获取到某一作者对象
get_book=author_obj.book.all() #获取到该作者对象对应的所有书籍
print(get_book)
2、创建:为某一个作者新增编写的书籍,会自动保存到多对多关系表中
会做两件事:第一件事是在book表中创建一个新增的书籍,第二件事是在作者与书的关系表中添加关联记录
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#创建:通过作者创建一本书
author_obj=Author.objects.all().first() #获取一个作者对象
author_obj.book.create(title='水浒传',publisher_id=1) #添加作者对象对应的书籍
3、添加:将现有一本书籍添加到作者当中,使得作者与该书籍有关联关系
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#多对多
#添加关系:某本书添加作者
book_obj=Book.objects.get(id=5) #获取一个书籍对象
author_obj=Author.objects.all().first() #获取一个作者对象
author_obj.book.add(book_obj) #作者与书籍新增关联关系
也可以直接添加书籍id进行添加
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#直接添加id添加关联关系
author_obj=Author.objects.all().first() #获取作者对象
author_obj.book.add(1) #直接添加书籍id
4、添加多个: 将现有多本书籍添加到作者当中,使得作者与该书籍有关联关系
注意:获取到多本书的对象集(列表形式),在add时需要将列表打散,使用*
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#添加关系:多本书添加作者关联关系
book_objs=Book.objects.filter(id__gt=2) #获取对象集(列表)
author_obj=Author.objects.all().first() #获取一个作者对象
author_obj.book.add(*book_objs) #作者与书籍新增关联关系,需要拆分
5、更新关联关系:更新某个作者对应书籍的关联关系
注意:set函数中的值一定要写成列表形式,更新为单个对应关系就在列表写一个值,例如[xxx],如果需要更新多个对应关系就在列表中写多个值,例如[xxxx,xxxx,xxxx],下面是更新了一条关联关系
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#多对多
#更新model对象的关联对象
author_obj=Author.objects.get(id=3) #获取作者对象
author_obj.book.set([4]) #更新关联对象
6、删除:删除某本书与作者的关联关系
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#多对多
#删除某一个与作者的关联关系的书籍
book_obj=Book.objects.get(id=1) #获取书籍对象
author_obj=Author.objects.all().first() #获取作者对象
author_obj.book.remove(book_obj) #删除关联关系
如上图可见,id为1的书籍和作者id为1的作者没有关联关系了,当然我们也可以直接通过书籍id直接删除
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#通过书籍id直接删除关联关系
author_obj=Author.objects.all().first() #获取作者对象
author_obj.book.remove(2) #通过书籍id直接删除关联关系
如上图可见,id为2的书籍和作者id为1的作者没有关联关系了
7、清空:将某个作者对应的所有书籍关联关系全部清空
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
#清空:将某个作者对应的书籍关联关系全部清空
author_obj=Author.objects.get(id=3) #获取作者对象
author_obj.book.clear() #清空作者对象的所有关联关系
如上图可见,作者id为3的已经没有书籍与之对应关联了
碎片四:聚合查询与分组查询
一、聚合查询
1、求平均值:求所有书籍的平均价格
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Avg
#聚合查询
avg_price=Book.objects.all().aggregate(Avg('price')) #求所有书籍的平均价格
print(avg_price)
2、求和:求所有书籍价格的总和
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Sum
#聚合查询
sum_price=Book.objects.all().aggregate(Sum('price')) #求所有书籍的总价格
print(sum_price)
3、求最大值:求所有书籍价格最大值
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Max
#聚合查询
max_price=Book.objects.all().aggregate(Max('price')) #求所有书籍的最大价格
print(max_price)
4、求最小值:求所有书籍价格最小值
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min
#聚合查询
min_price=Book.objects.all().aggregate(Min('price')) #求所有书籍的最小价格
print(min_price)
注意:我们可以手动指定key的值,这样得到的字典就是我们定义的key和获取到的值value
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min
#聚合查询
min_price=Book.objects.all().aggregate(get_minprice=Min('price')) #求所有书籍的最小价格
print(min_price)
print(min_price['get_minprice']) #获取到具体的值
5、多个聚合查询:计算出多个聚合的结果
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min,Max,Sum,Avg
#聚合查询
res=Book.objects.all().aggregate(min_price=Min('price'),max_price=Max('price'),
sum_price=Sum('price'),avg_price=Avg('price'))
print('最小价格:{}'.format(res['min_price']))
print('最大价格:{}'.format(res['max_price']))
print('价格总和:{}'.format(res['sum_price']))
print('平均价格:{}'.format(res['avg_price']))
二、分组查询
示例1:查询每一本书对应的作者的数量
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min,Max,Sum,Avg,Count
#分组查询
#查询每一本书的作者个数
#获取对象
get_objs=Book.objects.all().annotate(author_num=Count('author'))
for obj in get_objs:
print('书名:{},数量:{}'.format(obj.title,obj.author_num))
上面的代码解析:
1、通过Book表查询出所有的书籍
2、通过author_num即根据作者个数进行分组查询,就是group_by
3、将对象集反馈给get_objs,每个对象会多一个author_num属性
4、循环遍历出每个对象(每本书)对应的作者的数量(author_num)并打印出来
示例2:查询作者数量大于1的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min,Max,Sum,Avg,Count
#分组查询
#查询作者数量大于1的书
get_books=Book.objects.all().annotate(author_num=Count('author')).filter(author_num__gt=1)
for book in get_books:
print('书名:{},作者数量:{}'.format(book.title,book.author_num))
上面的代码解析:
1、通过Book表查询出所有的书籍
2、通过author_num即根据作者个数进行分组查询,就是group_by
3、分组后再通过作者数量进行查询,查询出作者数量大于1的书籍对象
4、将对象集反馈给get_books,每个对象会多一个author_num属性
5、循环遍历出每个对象(每本书)对应的作者的数量(author_num)并打印出来
示例3:求每个作者的书籍的总价格
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import Min,Max,Sum,Avg,Count
#分组查询
#查询各个作者出的书的总价格
get_authors=Author.objects.all().annotate(sum_price=Sum('book__price'))
for author in get_authors:
print('作者:{},书籍总价格:{}'.format(author.name,author.sum_price))
上面的代码解析:
1、首先在作者表Author表获取到全部的作者
2、通过书籍总价格进行分组,即group_by,此时我们需要得到作者对应的书籍并计算总价格,所以此时我们需要设置sum_price
3、利用聚合函数Sum,然后对book进行跨表查询出每个作者对应的每本书的价格,利用Sum求和后给sum_price
4、最后将获取到的分组查询对象集给get_authors,每个对象会多了一个sum_price属性
5、遍历get_authors,将每个作者author的名称与书籍总价格打印出来
碎片五:F查询与Q查询
一、F查询-用于同一张表两个字段比较
我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
示例1:查询库存数大于销售数的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import F,Q
#F&Q查询
#1、查询出库存数大于卖出数的所有书籍(两个字段做比较)
get_books=Book.objects.filter(kucun__gt=F('maichu'))
print(get_books)
上面的代码就是利用filter筛选出每种书籍库存数大于卖出数的对象,利用F(‘maichu’)去针对每个书籍对象去数据库获取出对应的卖出数量进行比较
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)
修改操作也可以使用F函数,比如将每一本书的价格提高30元
models.Book.objects.all().update(price=F("price")+30)
引申:
如果要修改char字段咋办?
示例1:把所有书名后面加上(第一版)
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import F,Q
from django.db.models.functions import Concat
from django.db.models import Value
#F&Q查询
#3、针对字符串进行F操作,在每本书的书名加上(第一版)
Book.objects.all().update(title=Concat(F('title'),Value('第一版')))
修改char字段时,我们需要导入Concat和Value,Concat用于字符串拼接,Value用于包裹字符串
二、Q查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象。
示例1:查询卖出数大于100或者价格小于100的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import F,Q
#F&Q查询
#4、Q查询,卖出数大于100或者价格小于100的书籍
get_obj=Book.objects.filter(Q(maichu__gt=100) | Q(price__lt=100))
print(get_obj)
<QuerySet [<Book: 2,《Python基础》第一版,2,北京大学出版社,成都市动物园>, <Book: 3,《Python Locust》第一版,3,西华大学出版社,成都市动物园>, <Book: 4,《自动化测试框架实践》第一版,1,清华大学出版社,成都市动物园>, <Book: 5,《测试开发实践》第一版,1,清华大学出版社,成都市动物园>, <Book: 8,《战狼7》第一版,4,蓝光coco国际出版社,蓝光coco国际二期>, <Book: 9,《流浪地球》第一版,4,蓝光coco国际出版社,蓝光coco国际二期>, <Book: 10,水浒传第一版,1,清华大学出版社,成都市动物园>]>
示例2:查询卖出数大于100并且价格小于100的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import F,Q
#F&Q查询
#Q查询,卖出数大于100并且价格小于100的书籍
get_obj=Book.objects.filter(Q(maichu__gt=100) & Q(price__lt=100))
print(get_obj)
<QuerySet [<Book: 3,《Python Locust》第一版,3,西华大学出版社,成都市动物园>, <Book: 8,《战狼7》第一版,4,蓝光coco国际出版社,蓝光coco国际二期>]>
示例3:查询卖出数大于100并且价格小于100并且书名包含Locust的书籍
import os
if __name__=='__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
import django
django.setup()
from bookapp.models import *
from django.db.models import F,Q
#F&Q查询
#Q查询结合自定义查询,查询卖出数大于100并且价格小于100并且书名包含Locust的书籍
get_book=Book.objects.filter(Q(maichu__gt=100) & Q(price__lt=100),title__contains='Locust')
print(get_book)
<QuerySet [<Book: 3,《Python Locust》第一版,3,西华大学出版社,成都市动物园>]>
注意:自定义查询条件只能写到Q查询的后面,不能写到Q查询的前面