數據準備python
class Publish(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) addr=models.CharField(max_length=64) email=models.EmailField def __str__(self): return self.name class Author(models.Model): id = models.AutoField(primary_key=True) name=models.CharField(max_length=32) sex=models.IntegerField() authordetail=models.OneToOneField(to='AuthorDetail',to_field='id') def __str__(self): return self.name class AuthorDetail(models.Model): id=models.AutoField(primary_key=True) phone = models.CharField(max_length=32) addr = models.CharField(max_length=64) class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) create_time = models.DateField(null=True) publish=models.ForeignKey(to='Publish',to_field='id') authors=models.ManyToManyField(to='Author') def __str__(self): return self.name ------------------------------------------------------- # 一對一的關係:OneToOneField 模型表的字段,後面會自定加_id # 一對多的關係:ForeignKey 模型表的字段,後面會自定加_id # 多對多的關係:ManyToManyField ManyToManyField會自動建立第三張表
方式一:git
pub=Publish.objects.get(pk=1) #publish=出版社的對象,存到數據庫,是一個id Book.objects.create(name='金庸羣俠傳',price=100,create_time='2018-1-1',publish=pub)
方式二:數據庫
book=Book.objects.create(name='紅樓夢',price=34.5,create_time='2017-1-1',publish_id=1) #用了OneToOneField和ForeignKey,模型表的字段,後面會自定加_id
方式一:django
#修改出版社 book=Book.object.get(pk=1) book.publish_id=2 book.save()
方式二:設計
book=Book.objects.filter(pk=1).update(publish_id=2) 或 pub=Publish.objects.get(pk=2) book=Book.objects.filter(pk=1).update(publish=pub)
同單表刪除code
方式一:對象
ret=models.Book.objects.filter(name='紅樓夢').delete() # ret返回的是被影響行數,queryset對象的.delete()方法 若是存在多本紅樓夢將會被所有刪除
方式二:ci
ret=models.Book.objects.filter(name='紅樓夢').first() ret.delete() 只刪除一個
a=Author.objects.filter(name='虛竹').first() b=Author.objects.filter(name='段譽').first() book=Book.objects.filter(name='天龍八部').first() #添加過個做者對象 book.authors.add(a,b) #或者 添加多個做者id book.authors.add(1,2)
book.authors.remove(a) book.authors.remove(1,2)
book.authors.clear()
book.authors.set([a,b])
基於對象的查詢是子查詢也就是屢次查詢
正向 author-----關聯字段在author----->authordetail------>按字段 反向 authordetail----->關聯字段在author---->author------>按表名小寫
例子rem
正向查詢:查詢abc做者的手機號get
author=Author.objects.filter(name='abc').first() authordetail=author.authordetail # author.authordetail 就是做者詳情的對象----這裏的authordetail是字段名 print(authordetail.phone)
反向查詢:查詢地址在上海的做者名字
authordetail=AuthorDetail.objects.filter(addr='上海').first() author=authordetail.author # authordetail.author 這是做者對象 print(author.name)
正向: book----關鍵字段在book--->publish---->按字段 反向: publish---->關鍵字段在book--->book---->按表名小寫_set.all()
正向查詢:查詢紅樓夢這本書的出版社地址
book=Book.objects.filter(name='紅樓夢').first() pub=book.publish #book.publish 出版社對象 print(pub.addr)
反向查詢:查詢地址是上海的出版社的出版圖書
pub=Publish.objects.filter(addr='上海').first() books=pub.book_set.all()
正向: book---關聯字段在book--->author--->按字段.all() 反向: author---關聯字段在book--->book---->按表名小寫_set.all()
正向查詢:查詢紅樓夢這本書的全部做者
book=Book.objects.filter(name='紅樓夢').first() authors=book.authors.all()
反向查詢:查詢B寫的全部書
b=Author.objects.filter(name='B').first() books=b.book_set.all()
查詢紅樓夢這本書全部的做者的手機號
book=Book.objects.filter(name='紅樓夢') authors=book.author.all() for author in authors: author_detail=author.authordetail print(authordetail.phone)
-正向:按字段,跨表能夠在filter,也能夠在values中 按字段 -反向:按表名小寫,跨表能夠在filter,也能夠在values中 按表名小寫
正向查詢:查詢做者B的手機號
(以author表做爲基表)
ret=Author.object.filter(name='B').values('authordetail__phone') print(ret)
反向查詢:
ret=AuthorDetail.object.filter(author__name='B').values('phone')
正向查詢:
#查詢出版社爲北京出版社出版的全部圖書的名字,價格 Book.objects.filter(publish_name='北京出版社').values('name','price')
反向查詢:
Publish.objects.filter(name='北京出版社').values('book_name','book_price')
正向查詢:
查詢紅樓夢的全部做者名字 Book.objects.filter(name='紅樓夢').values('authors_name')
反向查詢:
Author.objects.filter(book__name='紅樓夢').values('name')
查詢北京出版社出版過的全部書籍的名字以及做者的姓名
Publish.objects.filter('北京出版社').values('book__name','book_author__name')
Book.object.filter(publish__name='北京出版社').values('name','author__name')
aggregate
(*args, **kwargs)
aggregate()是QuerySet 的一個終止子句,返回一個包含一些鍵值對的字典 能夠向aggregate()子句中添加另外一個參數,生成不止一個聚合
from django.db.models import Avg,Count,Max,Min,Sum #1.計算全部圖書的平均價格 Book.objects.all().aggregate(Avg('price'),Max('price'))
annotate()爲調用的QuerySet中每一個對象生成獨立的統計值。跨表分組查詢本質就是將關聯表join成一張表,再按單表的思路進行分組查詢
#統計每一本書做者個數 Book.objects.all().annotate(s=Count('author')).values('name','c')
#查詢全部做者寫的書的總價格大於30的做者 Author.objects.value('pk')annotate(s=Sum('book_price')).filter(s_gt=30).values('name','s') 或者 Author.objects.annotate(s=Sum('book_price)).filter(s_gt=30).values('name''s') #默認按id主鍵分組
注:
values在annotate前表示分組,在後表示取值 filter在annotate前表示where條件,在後表示having
對兩個字段的值作比較 F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。
例如book的model中再添加兩個字段,評論數和閱讀數.
查詢評論數大於閱讀數的書
ret=Book.objects.all().filter(commit_num__gt=read_num) #錯誤 正確以下: ret=Book.objects.all().filter(commit_num_gt=F('read_num'))
把全部書的評論數加1
ret=Book.objects.all().update(commit_num=F('commit_num')+1)
filter()等方法進行的是'AND',更復雜的查詢須要Q查詢 表示與& ,或 | ,非 ~
#查詢是做者A也或者是做者B的書 Book.object.all().filter(Q(author_name='A')|Q(author_name='B'))
補充:
Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)
把兩個參數拆開,放在兩個filter調用裏面,Django在這種狀況下,將兩個filter之間的關係設計爲-或「or」