多表操做

多表操做

數據準備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會自動建立第三張表

1、一對多

1.添加數據

方式一: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

2.修改數據

方式一: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)

3.刪除數據

同單表刪除code

方式一:對象

ret=models.Book.objects.filter(name='紅樓夢').delete()
# ret返回的是被影響行數,queryset對象的.delete()方法
若是存在多本紅樓夢將會被所有刪除

方式二:ci

ret=models.Book.objects.filter(name='紅樓夢').first()
ret.delete()
只刪除一個

2、多對多

1.添加數據

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)

2.刪除remove,能夠傳對象,能夠傳id,能夠傳多個,不要混着用

book.authors.remove(a)
book.authors.remove(1,2)

3.clear清空全部

book.authors.clear()

4.set,先清空全部,再新增,要傳一個列表,列表內能夠是id,也能夠是對象

book.authors.set([a,b])

3、基於對象的跨表查詢

基於對象的查詢是子查詢也就是屢次查詢

1.一對一

正向  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)

2.一對多

正向: 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()

3.多對多

正向: 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()

4.連續跨表

查詢紅樓夢這本書全部的做者的手機號

book=Book.objects.filter(name='紅樓夢')
authors=book.author.all()
for author in authors:
    author_detail=author.authordetail
    print(authordetail.phone)

4、基於雙下劃線查詢

1.一對一

-正向:按字段,跨表能夠在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')

2.一對多

正向查詢:

#查詢出版社爲北京出版社出版的全部圖書的名字,價格
Book.objects.filter(publish_name='北京出版社').values('name','price')

反向查詢:

Publish.objects.filter(name='北京出版社').values('book_name','book_price')

3.多對多

正向查詢:

查詢紅樓夢的全部做者名字
Book.objects.filter(name='紅樓夢').values('authors_name')

反向查詢:

Author.objects.filter(book__name='紅樓夢').values('name')

4.連續跨表

查詢北京出版社出版過的全部書籍的名字以及做者的姓名

Publish.objects.filter('北京出版社').values('book__name','book_author__name')
Book.object.filter(publish__name='北京出版社').values('name','author__name')

5、聚合查詢

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'))

6、分組查詢

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

7、F查詢

對兩個字段的值作比較
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)

8、Q查詢

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」

相關文章
相關標籤/搜索