Django多變關聯、增加數據、刪除數據


 建立表之間的關聯關系:

models.py里面對表的字段及外鍵關系的設置如下:

from django.db import models

# Create your models here.

#出版社表
class Publish(models.Model):
    nid=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

#作者表(與AuthorDetail是一對一關系)
class Author(models.Model):
    nid=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    #建立與AuthorDetail一對一關系
    authordetail=models.OneToOneField(to='AuthorDetail',to_field='nid')

    def __str__(self):
        return self.name

#作者詳細信息表
class AuthorDetail(models.Model):
    nid=models.AutoField(primary_key=True)
    phone=models.CharField(max_length=32)
    email=models.EmailField()

    def __str__(self):
        return self.phone

#書籍表
class Book(models.Model):
    nid=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=5,decimal_places=2)
    pub_date=models.DateField()
    #與出版社綁定一對多關系
    publish=models.ForeignKey(to='Publish',to_field='nid')

    #與作者綁定多對多關系(會生成第三張表)
    authors=models.ManyToManyField(to='Author')

    def __str__(self):
        return self.name

 執行后生成的表格關系圖,如下:

 增加數據:

1.一對一表的增加

#增加
#一對一表的增加(Author--AuthorDetail)
    #先創建沒有外鍵的數據,即先建作者詳細表
    # authordetail=AuthorDetail.objects.create(phone='3333333',email='1333@qq.com')
    # print(authordetail,type(authordetail)) #AuthorDetail object <class 'app01.models.AuthorDetail'>
    # print(authordetail.email) #1333@qq.com

    #author建立方式一:手動指定關聯authordetail表
    # author=Author.objects.create(name='作者1',age=13,authordetail_id=2)
    # print(author) #作者1

    #author建立方式二:可以傳個對象(默認綁定的就是作者詳情表里面的最后一條記錄)
    # author = Author.objects.create(name='作者2', age=13, authordetail=authordetail)
    # print(author) #作者2

    #一對多表的增加(Book--Publish)
    # Publish.objects.create(name='北京出版社',addr='北京',email='11@qq.com')
    # publish=Publish.objects.create(name='南京出版社',addr='南京',email='22@qq.com')
    # print(publish) #南京出版社
    # publish=Publish.objects.create(name='廣州出版社',addr='廣州',email='33@qq.com')

    # book=Book.objects.create(name='在路上',price=23.1,pub_date='2011-01-23',publish=publish)
    # print(book)  #在路上

    #注意的點,關聯鍵傳的時候要不是手動指定相關表的id號,要不就是只能傳對象,例如下面操作:
    # publish=Publish.objects.filter(name='北京出版社') #注意這里拿到的是queryset對象
    # print(publish) #<QuerySet [<Publish: 北京出版社>]>

    # publish = Publish.objects.filter(name='北京出版社').first() #是對象
    # print(publish)  # 北京出版社
    #手動創建一本書去,通過出版社對象.nid 與對象的‘北京出版社’做綁定
    # book=Book.objects.create(name='你若安好',price=23,pub_date='1991-1-3',publish_id=publish.nid)

 2.多對多表的增加

#多對多表的添加add(通過Book、Author2張表,在book_authors表里面錄入信息,完成多對多的綁定關系)
    #方式一:add(作者的id,作者的id)
    # book=Book.objects.create(name='紅樓夢',price=120,pub_date='1891-01-11',publish_id=1)
    # print(book)
    # print(book.authors.all(),type(book.authors)) #book.authors類型是manager
    #將紅樓夢書綁定作者1、作者2
    # res=book.authors.add(1,2)
    # ret=book.authors.add(*(2,5))


    #方式二:add(作者的對象)
    #第一步:先拿到你想關聯的作者的對象
    # author=Author.objects.filter(nid=2).first()
    # print(author) #作者2

    #第二步:直接將對象傳給add(),即可以將下面書和上面的作者,在第三種表里完成綁定關系並錄入
    # book=Book.objects.filter(name='便是晴天').first()  #記得傳的一定要是對象
    # book.authors.add(author)

 解除表之間的綁定關系(remove、clear、set)

#解除綁定
# Remove依次刪除一條或多條
    # book=Book.objects.filter(nid=4).first()
    # print(book)
    #手動指定id結果關聯
    #移除nid=4的書與 nid=2的作者 的綁定
    # res=book.authors.remove(2)
    # print(res)

    #傳對象解除關聯
    # author=Author.objects.filter(nid=2).first()
    # book=Book.objects.filter(nid=3).first()
    # ret=book.authors.remove(author)
    # print(ret) #None

    #如果1本書綁定的有多個作者,可以傳多個值
    # ret=book.authors.remove(2,5)
    # ret=book.authors.remove(*(2,5))


# clear 一次性全部解除綁定關系
    # book = Book.objects.filter(pk=9).first()
    # book.authors.clear()


#set 用法,參數必須傳可迭代對象,可以傳id,也可以傳對象

    #方式一:傳nid
    #先解除所有與書nid=3的所有綁定
    # book=Book.objects.filter(nid=3).first()
    # #再建立一個新的與作者nid=3的綁定
    # res=book.authors.set([3])  #一定是個可迭代的對象
    # print(res)

    #方式二:傳對象
    # book=Book.objects.filter(nid=2).first()
    # #會先執行上面與書2的綁定,再執行下面新的綁定
    # author=Author.objects.filter(nid=2).first() #author是個對象
    # book.authors.set([author]) #傳一個可迭代對象

 set( [ 可迭代對象] )的用法圖解:

用法一:

#方式一:傳nid
#先解除所有與書nid=3的所有綁定
# book=Book.objects.filter(nid=3).first()
# #再建立一個新的與作者nid=3的綁定
# res=book.authors.set([3]) #一定是個可迭代的對象
# print(res)

用法二:

#方式二:傳對象
book=Book.objects.filter(nid=2).first()
#會先執行上面與書2的綁定,再執行下面新的綁定
author=Author.objects.filter(nid=2).first() #author是個對象
book.authors.set([author]) #傳一個可迭代對象 

多對多關系表查詢圖解:

1.正常查詢:按字段 ,

 #正向查詢(按照字段):查詢‘你過安好’這本書對應的作者
    #Book是book表的一個對象   book.author.all()是author表的一個對象
    book=Book.objects.filter(name='你若安好').first()
    print(book.authors,type(book.authors))    #這個得到的是manager
    #注意點:不同於一對多的表,最后通過書查對應的出版社,只會找到一個所有直接就調用屬性就行,例如print(book.publish.name)
    print(book.authors.all())   #<QuerySet [<Author: 作者1>, <Author: 作者2>]>

2.反向查詢:表名小寫_set.all()

 #反向查詢():查詢作者3所寫的書有哪些
    author=Author.objects.filter(name='作者3').first()
    print(author.book_set.all())  #<QuerySet [<Book: 紅樓夢>, <Book: 在路上>]> 

查詢數據:

 總結:用__告訴orm,要連接那個表
      一對一: 正向:按字段  反向:按表名小寫 
      一對多:  正向:按字段  反向:按表名小寫 
      多對多:  正向:按字段  反向:按表名小寫 

基於對象的多表查詢

1.一對一

#一對一
    #正向查詢(按關鍵字authordetail段來查):查詢作者1的電話號碼
    #先定位到要找哪個作者
    # author=Author.objects.filter(name='作者1').first()
    # print(author.authordetail) #是個對象
    #根據關鍵字段來查對應的iphone
    # print(author.authordetail.phone) #456789

    # 反向查詢(表名小寫):查詢電話號碼是456789的作者
    # authordetail=AuthorDetail.objects.filter(phone='456789').first()
    # print(authordetail.author) #作者1

 2.一對多

#一對多
    #正向查詢(按關鍵字publish段來查):查詢‘在路上’這本書多對相應的出版社app01_authordetail
    # book=Book.objects.filter(name='在路上').first()
    # print(book.publish,type(book.publish))    #這個得到是對象
    # print(book.publish.name) #廣州出版社

    #反向查詢(按照表名小寫_set)
    # publish=Publish.objects.filter(name='廣州出版社').first()
    # print(publish.book_set,type(publish.book_set)) #book_set 是namage對象
    # print(publish.book_set.all())  #<QuerySet [<Book: 在路上>]>

3.多對多

#多對多
    #正向查詢(按照字段):查詢‘你過安好’這本書對應的作者
    #Book是book表的一個對象   book.author.all()是author表的一個對象
    # book=Book.objects.filter(name='你若安好').first()
    # print(book.authors,type(book.authors))    #這個得到的是manager
    #注意點:不同於一對多的表,最后通過書查對應的出版社,只會找到一個所有直接就調用屬性就行,例如print(book.publish.name)
    # print(book.authors.all())   #<QuerySet [<Author: 作者1>, <Author: 作者2>]>


    #反向查詢():查詢作者3所寫的書有哪些
    # author=Author.objects.filter(name='作者3').first()
    # print(author.book_set.all())  #<QuerySet [<Book: 紅樓夢>, <Book: 在路上>]> 

基於雙下划線的多表查詢:

1.一對一

#一對一
    #查詢作者1的手機號(正向)
    # res1=Author.objects.filter(name='作者1').values('authordetail__phone')
    # print(res1) #<QuerySet [{'authordetail__phone': '456789'}]>

    #反向實現(根據作者詳情找到作者表對應的手機號)
    # res2 = AuthorDetail.objects.filter(author__name='作者1').values('phone')
    # print(res2) #<QuerySet [{'phone': '456789'}]>

 2.一對多

#基於雙下划線的多表查詢(連表查詢)   publish__就相當於連接得到publish這張表
#一對多
    #正向查詢:從書出發直接去找,對應出版社的書的信息(按字段__name)
    # res = Book.objects.filter(publish__name='北京出版社').values('price', 'name')
    # print(res)

    #反向查詢
    #查詢北京出版社出版過的所有書籍價格,名字(反向按表名)
    # res = Publish.objects.filter(name='北京出版社').values('book__price', 'book__name')
    # print(res)  # <QuerySet [{'book__price': Decimal('23.00'), 'book__name': '你若安好'}, ..,>

 3.多對多

#多對多
    #查詢作者3 出版過的所有書的名字
    #正向查詢(按字段__ ,例如:authors__)
    # res1=Book.objects.filter(authors__name='作者3').values('name','price')
    # print(res1) #<QuerySet [{'name': '在路上', 'price': Decimal('23.10')}, {'name': '紅樓夢', 'price': Decimal('120.00')}]>

    #反向查詢(表名小寫__)
    # res2=Author.objects.filter(name='作者3').values('book__name','book__price')
    # print(res2) #<QuerySet [{'book__name': '在路上', 'book__price': Decimal('23.10')}, {'book__name': '紅樓夢', 'book__price': Decimal('120.00')}]>

 聚合函數aggregate():

#聚合函數aggregate(*args,**kwargs),返回的是個字典

#計算所有圖書的平均價格: Avg()
from django.db.models import Avg,Count,Max,Min,Sum
# ret=Book.objects.all().aggregate(c=Avg('price'))
# print(ret) #{'c': 44.275}


#計算所有圖書總價:Sum()
# ret=Book.objects.all().aggregate(s=Sum('price'))
# print(ret) #{'s': Decimal('177.10')}


 #最大價格:Max
# ret=Book.objects.all().aggregate(m=Max('price'))
# print(ret) #{'m': Decimal('120.00')}

#最大值、最小值
# ret=Book.objects.all().aggregate(c_max=Max('price'),c_min=Min('price'))
# print(ret) #{'c_max': Decimal('120.00'), 'c_min': Decimal('11.00')}

anootate:分組

 

annotate()為調用的QuerySet中每一個對象都生成一個獨立的統計值(統計方法用聚合函數)。

 

總結 :跨表分組查詢本質就是將關聯表join成一張表,再按單表的思路進行分組查詢。

 

 

F()、Q()函數:

# F與Q函數
from django.db.models import F,Q
#查詢評論數大於閱讀數的所有書
#F F()的實例可以在查詢中引用字段,
commit_num:評論數字段   read_num:閱讀數字段(因為沒有辦法直接做比較,所有因為F函數)
ret=Book.objects.filter(commit_num__gt=F('read_num')).values('name')
print(ret)

#把所有書的價格+1
ret=Book.objects.all().update(price=F('price')+1)
print(ret) #4 更新了4條記錄

# Q函數 |或  &和
#Q函數名字叫
ret= Book.objects.filter(Q(name='紅樓夢')|Q(price='12')) #回去出紅樓夢和價格12的2個對象
print(ret)  #<QuerySet [<Book: 紅樓夢>, <Book: 便是晴天>]>

#不存在的情況,會返回空
ret= Book.objects.filter(Q(name='紅樓夢')&Q(price='12')) #&並且的意思
print(ret)  #<QuerySet []>如果沒找到,不會報錯,會為空

#驗證&
ret= Book.objects.filter(Q(name='紅樓夢')&Q(price='121'))
print(ret) #<QuerySet [<Book: 紅樓夢>]>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM