说明我们在设计SQL语句的时候,将表仔细创建,这里很重要,后期就最好不要动了
设计表,将各个表之间的对应关系梳理清楚,这是对表查询的重要的步骤
多表操作
一对一:
增删改查
model.Author.objects.create(name='二哥',age=59,ad_id=1)
删除
model.Author.objects.filter(id=1).delete()
改
model.Author.objects.filter(id=1).update(name='2ge2')
查
正向:
model.Author.objects.filter(id=1)[0].ad.telephone
反向
ad_obj = model.AuthorDetail.objects.filter(telephone=111)[0]
ad_obj.author.id
一对多:
增加:
model.Book.objects.create(title='xx',price=12,publish_id=1)
model.Book.objects.create(title='xx',price=12,publish=publish的model对象)
删除
model.Book.objects.filter(id=3)[0].delete()
model.Book.objects.filter(id=3).delete()
修改:
model.Book.objects.filter(id=3).update(title='xxx',publish_id=2)
查询
反向查询:红浪漫出版社出版过哪些书籍(只要名称)
pub_obj = model.Publish.objects.filter(name='红浪漫出版社').first()
pub_obj. book_set.all().value() .value_list()
.filter(xxx=xxx)
author_obj = models.Author.objects.get(name='二哥')
print(author_obj.book_set.all().values('title').filter(title='linux')) # <QuerySet [{'title': 'linux'}, {'title': 'linux'}]>
正向查询:
book_obj = models.Book.objects.filter(title='jinpinmei').first()
book_obj .publish.name
多对多的
增加
book_obj = models.Book.objects.create(title='水浒',price=11,publish_id=1)
authorerge = models.Author.objects.get(name='二哥')
authorsange = models.Author.objects.get(name='三哥')
book_obj.authors.add(*[authorerge,authorsange])
book_obj.authors.add(*[authorerge.id,authorsange.id])
删除
book_obj.authors.remove(authorerge)
book_obj.authors.remove(1)
book_obj.authors.remove(1,2,3)
book_obj.authors.remove(*[1,2,3])
book_obj.authors.clear()
book_obj.authors.set(['1','2',])
查询:
正向查询:
book_obj = models.Book.objects.get(title='水浒')
book_obj.authors.all().values('name'),.values_list('name')
book_obj.authors.filter()
反向查询
authorsange = models.Author.objects.get(name='三哥')
authorsange.book_set.all().values('title')
基于双下划线的查询
一对一
查一下雄哥的手机号
models.Author.objects.filter(name='雄哥').values('ad__telephone')
models.AuthorDetail.objects.filter(author__name='雄哥').values('telephone')
一对多
红浪漫出版了哪些书
models.Publish.objects.filter(name='红浪漫出版社').values('book__title')
models.Book.objects.fitler(publishs__name='红浪漫出版社').values('title')
多对多
python这本书是哪些作者写的
models.Book.objects.filter(title='python').values('authors__name')
models.Author.objects.filter(book__title='python').values('name')
聚合
查询一下所有书的平均价格
from django.db.models import Avg,Max,Min,Count,Sum
models.Book.objects.all().aggregate(a=Avg('price')) #结果是个字典
分组
查询作者出版过的书的平均价格
models.Author.objects.values('name').annotate(a=Avg('book__price'))
#这里annotate是分组,以name分组
#annotate只能以前面的values作为分组条件,如果没有则以第一个表的ID分组
models.Book.objects.values('authors__name').annotate(a=Avg('price'))
F
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?我们在book表里面加上两个字段:评论数:commentNum,收藏数:KeepNum
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
我先查看点赞数小于评论数的所有书籍
from django.db.models import F
model.Book.objects.filter(zan__lt=F('comment'))
统一给价格加100块
model.Book.objects.all().update(price=F('price')+100)
Q
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
Q 对象可以使用&(与) 、|(或)、~(非) 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
查询2019年的点赞数小于100的,或者评论小于100的书籍名称和价格
models.Book.objects.filter(Q(zan__lt=100)|Q(comment__lt=100),date__year=2019).values('title','price')
#1 查询每个作者的姓名以及出版的书的最高价格
ret = models.Author.objects.annotate(m=Max('book__price')).values('name','m')
#这里annotate是分组,以Author表中的ID分组,其中values省略了
#annotate只能以前面的values作为分组条件
#ret 获取到的值是annotate里面的m值和id的值,如果想要更多则在后面添加values写自己需要的值
ret = models.Book.objects.values('authors__name').annotate(m=Max('price'))
print(ret)
#2 查询作者id大于2作者的姓名以及出版的书的最高价格
models.Author.objects.filter(id__gt=2).annotate(m=Max('book__price')).values('name','m')
#3 查询作者id大于2或者作者年龄大于等于20岁的,女作者的姓名以及出版的书的最高价格
models.Author.objects.filter(Q(sex='女')&Q(Q(id__gt=2)|Q(age__gte=20))).values('name').annotate(m=Max('book__price'))
#4 查询每个作者出版的书的最高价格 的平均值
models.Author.objects.values('id').annotate(a=Max('book__price')).aggregate(m=Avg('a'))
#5 每个作者出版的所有书的最高价格的那本书的名称
models.Author.objects.values('name').annotate(a=Max('book__price')).values('book__title')