#models.py from django.db import models class Book(models.Model): nid=models.AutoField(primary_key=True) title=models.CharField(max_length=32) pubDate=models.DateField() price=models.DecimalField(max_digits=6,decimal_places=2) read_num=models.IntegerField(default=0) comment_num=models.IntegerField(default=0) #书籍与出版社:一对多 publisher=models.ForeignKey('Publish', related_name='bookList') #书籍与作者:多对多 authors=models.ManyToManyField('Author') def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) addr=models.CharField(max_length=32) tel=models.BigIntegerField() def __str__(self): return self.name class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() tel=models.CharField(max_length=32) def __str__(self): return self.name class AuthorDetail(models.Model): addr=models.CharField(max_length=32) author=models.OneToOneField('Author') #生成的第三张表的表名是 app01_book_authors,但是我们不能直接操作这张表
ORM跨表添加
1.一对多添加
1.publish_obj=Publish.objects.get(id=2) 表.objects.create(title='python',publisher=publish_obj) 2.表.objects.create(title='python',publisher_id=2)
2.多对多添加
authors=models.ManyToManyField('Author') #与这本书关联的作者对象集合 book_obj=models.Book.objects.create(title=title,pubDate=pubdate,price=price,publisher_id=publish_id) #方式1 print(book_obj.authors.all()) #QuerySet [] alex=models.Author.objects.get(name='alex') egon=models.Author.objects.get(name='egon') #绑定关系 book_obj.authors.add(alex,egon) print(book_obj.authors.all()) #QuerySet [author_alex,author_egon] #方式2 author_list=models.Author.objects.all() book_obj.authors.add(*author_list) #解除关系 book_obj=models.Book.objects.get(nid=14) print(book_obj.authors.all()) alex=models.Author.objects.get(name='alex') book_obj.authors.remove(alex) author_list=models.Author.objects.filter(id__gt=1) book_obj.authors.remove(*author_list) #清空 book_obj.authors.clear()
ORM跨表查询
1.基于对象的跨表查询
正向查询按字段,反向查询按表名(小写)_set
一对多跨表查询 1.查询python这本书出版社的地址 book_obj=Book.objects.get(title=python) book_obj.publisher.addr
多对多跨表查询 1.查询python这本书的所有作者的姓名和年龄 book_python=models.Book.objects.get(title='python') author_list=book_python.authors.all() for author in author_list: print(author.name,author.age) book_python=models.Book.objects.filter(title='python') for book_python in book_pythons: author_list=book_python.authors.all() for author in author_list: print(author.name,author.age)
1.查询人民出版社出版过的书籍名称及价格 pub_obj=models.Publish.objects.get(name='renmin') book_list=pub_obj.book_set.all() 或 book_list=pub_obj.bookList.all() #Query 与这个出版社关联的所有书籍对象 for obj in book_list: print(obj.title,obj.price) 2.alex出版过的所有书籍的名称 alex=models.Author.objects.get(name='alex') book_list=alex.book_set.all() for book in book_list: print(book.title,book.price)
一对一正向查询 查询addr在沙河的作者 authorDetail=models.AuthorDetail.objects.get(addr='shahe') print(authorDetail.author.name) 一对一反向查询:按表名(小写),不需要加_set 查询alex在哪里 alex=models.Author.objects.get(name='alex') alex.authordetail.addr
2.基于双下划线的跨表查询
正向查询按字段,反向查询按关联的表名
#查询python这本书的价格 ret=models.Book.objects.filter(title='python').values('price','title') print(ret)
#查询python这本书出版社的地址和名称 正向查询:按字段 ret2=models.Book.objects.filter(title='python').values_list('publisher__name','publisher__addr') print(ret2) 反向查询:按表名 ret3=models.Publish.objects.filter(bookList__title='python').values_list('name','addr') print(ret3)
#查询人民出版社出版过的所有书籍名称和价格 models.Book.objects.filter(publisher__name='renmin').values('title','price') models.Publish.objects.filter(name='renmin').values('bookList__name','bookList_price')
#查询egon出版过的所有书籍的名字(多对多) models.Author.objects.filter(name='egon').values('book__title') models.Book.objects.filter(authors__name='egon').values('title')
#地址以沙河开头的作者出版过的所有书籍名称以及出版社名称 ret=models.Book.objects.filter(authors__authordetail__addr__startswith='sha').values('title','publisher__name') print(ret.count())
聚合与分组
1.聚合函数 SUM AVG MIN MAX COUNT
2.聚合函数可以单独使用,不一定要和分组配合使用;只不过聚合函数与group by搭配
aggregate()
#单纯聚合函数 #计算所有图书的平均价格 from django.db.models import Avg,Count,Sum,Min,Max models.Book.objects.all().aggregate(Avg('price'))
annotate() 返回queryset
为QuerySet重的每一个对象都生成一个独立的汇总值 #统计每一本书的作者个数 ret=models.Book.objects.all().annotate(auathors_num=Count('authors')) for obj in ret: print(obj.nid,obj.title,obj.author_num) #查询每一个出版社出版过的所有书籍的总价格 ret=models.Publish.objects.all().annotate(priceSum=Sum('bookList__price')) for obj in ret: print(obj.id,obj.name,obj.priceSum) 或 ret=models.Book.objects.all().values('publisher__name').annotate(priceSum=Sum('price')).values('publisher__name','priceSum')
F查询与Q查询
from django.db.models import F,Q ret1=models.Book.objects.filter(comment_num__gt=50) ret2=models.Book.objects.filter(comment_num__gt=F('read_num')) #评论数大于2倍阅读数的文章 ret3=models.Book.objects.filter(comment_num__gt=F('read_num')*2) #给每本书涨价10元 models.Book.objects.all().update(F('price')+10)
#查询评论数大于500或阅读数也大于50并且价格低于100 models.Book.objects.filter((Q(comment_num__gt=50)|Q(read_num__gt=50))&Q(price__lt=100))