Django教程五

聚合查詢

  • 聚合查詢是指對一個數(shù)據(jù)表中的一個字段的數(shù)據(jù)進(jìn)行部分或全部進(jìn)行統(tǒng)計(jì)查詢,查bookstore_book數(shù)據(jù)表中的全部書的平均價(jià)格,查詢所有書的總個數(shù)等,都要使用聚合查詢
  1. 不帶分組聚合

    • 不帶分組的聚合查詢是指導(dǎo)將全部數(shù)據(jù)進(jìn)行集中統(tǒng)計(jì)查詢

    • 聚合函數(shù):

      • 定義模塊: django.db.models
      • 用法: from django.db.models import *
      • 聚合函數(shù):
        • Sum, Avg, Count, Max, Min
    • 語法:

      • MyModel.objects.aggregate(結(jié)果變量名=聚合函數(shù)('列'))
    • 返回結(jié)果:

      • 由 結(jié)果變量名和值組成的字典
      • 格式為:
        • {"結(jié)果變量名": 值}
    • 示例:

      # 得到所有書的平均價(jià)格
      from bookstore import models
      from django.db.models import Count
      result = models.Book.objects.aggregate(myAvg=Avg('price'))
      print("平均價(jià)格是:", result['myAvg'])
      print("result=", result)  # {"myAvg": 58.2}
      
      # 得到數(shù)據(jù)表里有多少本書
      from django.db.models import Count
      result = models.Book.objects.aggregate(mycnt=Count('title'))
      print("數(shù)據(jù)記錄總個數(shù)是:", result['mycnt'])
      print("result=", result)  # {"mycnt": 10}
      
      
  2. 分組聚合

    • 分組聚合是指通過計(jì)算查詢結(jié)果中每一個對象所關(guān)聯(lián)的對象集合,從而得出總計(jì)值(也可以是平均值或總和),即為查詢集的每一項(xiàng)生成聚合。

    • 語法:

      • QuerySet.annotate(結(jié)果變量名=聚合函數(shù)('列'))
    • 用法步驟:

      1. 通過先用查詢結(jié)果MyModel.objects.value. 查找查詢要分組聚合的列

        • MyModel.objects.value('列1', '列2')

        • 如:

          pub_set = models.Book.objects.values('pub')
          print(books)  # <QuerySet [{'pub': '清華大學(xué)出版社'}, {'pub': '清華大學(xué)出版社'}, {'pub_hou {'pub': '機(jī)械工業(yè)出版社'}, {'pub': '清華大學(xué)出版社'}]>
          
          
      2. 通過返回結(jié)果的 QuerySet.annotate 方法分組聚合得到分組結(jié)果

        • QuerySet.annotate(名=聚合函數(shù)('列'))

        • 返回 QuerySet 結(jié)果集,內(nèi)部存儲結(jié)果的字典

        • 如:

          pub_count_set = pub_set.annotate(myCount=Count('pub'))
          print(pub_count_set)  # <QuerySet [{'pub': '清華大學(xué)出版社', 'myCount': 7}, {'pub': '機(jī)械工業(yè)出版社', 'myCount': 3}]>
          
          
      • .values('查詢列名')
    • 示例:

      • 得到哪兒個出版社共出版多少本書
      def test_annotate(request):
         - from django.db.models import Count
          from . import models
      
          # 得到所有出版社的查詢集合QuerySet
          pub_set = models.Book.objects.values('pub')
          # 根據(jù)出版社查詢分組,出版社和Count的分組聚合查詢集合
          pub_count_set = pub_set.annotate(myCount=Count('pub'))  # 返回查詢集合
          for item in pub_count_set:
              print("出版社:", item['pub'], "圖書有:", item['myCount'])
          return HttpResponse('請查看服務(wù)器端控制臺獲取結(jié)果')
      
      

F對象

  • 一個F對象代表數(shù)據(jù)庫中某個字段的信息
  • F對象通常是對數(shù)據(jù)庫中的字段值在不加載到內(nèi)存中的情況下直接在數(shù)據(jù)庫服務(wù)器端進(jìn)行操作
  • F對象在 數(shù)據(jù)包 django.db.models 中.使用時需要通過如下語句進(jìn)行加載
    • from django.db.models import F
  1. 作用:

    • 用于類屬性(字段)之間的比較。
    • 當(dāng)同時對數(shù)據(jù)庫中兩個字段的值進(jìn)行比較獲取 QuerySet 數(shù)據(jù)集時,可以便用F對象
  2. 說明:

    • 一個 F() 對象代表了一個model的字段的值
  3. 使用它就可以直接參考model的field和執(zhí)行數(shù)據(jù)庫操作而不用再把它們(model field)查詢出來放到python內(nèi)存中。

  4. 語法:

    from django.db.models import F
    F('列名')
    
    
  5. 示例1

    • 更新Book實(shí)例中所有的零售價(jià)漲10元
    models.Book.objects.all().update(market_price=F('market_price')+10)
    # 以下做法好于如下代碼
    books = models.Book.objects.all()
    for book in books:
        book.update(market_price=book.marget_price+10)
        book.save()
    
    
  6. 示例2

    • 對數(shù)據(jù)庫中兩個字段的值進(jìn)行比較,列出哪兒些書的零售價(jià)高于定價(jià)?
    from django.db.models import F
    from bookstore import models
    books = models.Book.objects.filter(market_price__gt=F('price'))
    for book in books:
        print(book.title, '定價(jià):', book.price, '現(xiàn)價(jià):', book.market_price)
    
    

Q對象 - Q()

  • 當(dāng)在獲取查詢結(jié)果集 使用復(fù)雜的邏輯或 | 、 邏輯非 ~ 等操作時可以借助于 Q對象進(jìn)行操作

  • 如: 想找出定價(jià)低于20元 或 清華大學(xué)出版社的全部書,可以寫成

    models.Book.objects.filter(Q(price__lt=20)|Q(pub="清華大學(xué)出版社"))
    
    
  • Q對象在 數(shù)據(jù)包 django.db.models 中。需要先導(dǎo)入再使用

    • from django.db.models import Q
  1. 作用

    • 在條件中用來實(shí)現(xiàn)除 and(&) 以外的 or(|) 或 not(~) 操作
  2. 運(yùn)算符:

    • & 與操作
    • | 或操作
    • ? 非操作
  3. 語法

    from django.db.models import Q
    Q(條件1)|Q(條件2)  # 條件1成立或條件2成立
    Q(條件1)&Q(條件2)  # 條件1和條件2同時成立
    Q(條件1)&~Q(條件2)  # 條件1成立且條件2不成立
    ...
    
    
  4. 示例

    from django.db.models import Q
    # 查找清華大學(xué)出版社的書或價(jià)格低于50的書
    models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清華大學(xué)出版社'))
    # 查找不是機(jī)械工業(yè)出版社的書且價(jià)格低于50的書
    models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='機(jī)械工業(yè)出版社'))
    
    

原生的數(shù)據(jù)庫操作方法

使用MyModel.objects.raw()進(jìn)行 數(shù)據(jù)庫查詢操作查詢
  • 在django中,可以使用模型管理器的raw方法來執(zhí)行select語句進(jìn)行數(shù)據(jù)查詢
  1. 語法:

    • MyModel.objects.raw(sql語句)
  2. 用法

    • MyModel.objects.raw('sql語句')
  3. 返回值:

    • QuerySet 集合對象
  4. 示例

    books = models.Book.objects.raw('select * from bookstore_book')
    
    for book in books:
        print(book)
    
    
使用django中的游標(biāo)cursor對數(shù)據(jù)庫進(jìn)行 增刪改操作
  • 在Django中可以使用 如UPDATE,DELETE等SQL語句對數(shù)據(jù)庫進(jìn)行操作。

  • 在DJaogo中使用上述非查詢語句必須使用游標(biāo)進(jìn)行操作

  • 使用步驟:

    1. 導(dǎo)入cursor所在的包
      • Django中的游標(biāo)cursor定義在 django.db.connection包中,使用前需要先導(dǎo)入
      • 如:
        • from django.db import connection
    2. 用創(chuàng)建cursor類的構(gòu)造函數(shù)創(chuàng)建cursor對象,再使用cursor對象,為保證在出現(xiàn)異常時能釋放cursor資源,通常使用with語句進(jìn)行創(chuàng)建操作
      • 如:

        from django.db import connection
        with connection.cursor() as cur:
            cur.execute('執(zhí)行SQL語句')
        
        
    • 示例

      # 用SQL語句將id 為 10的 書的出版社改為 "XXX出版社"
      from django.db import connection
      with connection.cursor() as cur: 
          cur.execute('update bookstore_book set pub_house="XXX出版社" where id=10;')
      
      with connection.cursor() as cur:
          # 刪除 id為1的一條記錄
          cur.execute('delete from bookstore_book where id=10;')
      
      

admin 后臺數(shù)據(jù)庫管理

  • django 提供了比較完善的后臺管理數(shù)據(jù)庫的接口,可供開發(fā)過程中調(diào)用和測試使用
  • django 會搜集所有已注冊的模型類,為這些模型類提拱數(shù)據(jù)管理界面,供開發(fā)者使用
  • 使用步驟:
    1. 創(chuàng)建后臺管理帳號:

      • 后臺管理--創(chuàng)建管理員帳號

        • $ python3 manage.py createsuperuser
        • 根據(jù)提示完成注冊,參考如下:
        $ python3 manage.py createsuperuser
        Username (leave blank to use 'tarena'): tarena  # 此處輸入用戶名
        Email address: weimz@tedu.cn  # 此處輸入郵箱
        Password: # 此處輸入密碼(密碼要復(fù)雜些,否則會提示密碼太簡單)
        Password (again): # 再次輸入重復(fù)密碼
        Superuser created successfully.
        $ 
        
        
    2. 用注冊的帳號登陸后臺管理界面

自定義后臺管理數(shù)據(jù)表

  • 若要自己定義的模型類也能在 /admin 后臺管理界中顯示和管理,需要將自己的類注冊到后臺管理界面
  • 添加自己定義模型類的后臺管理數(shù)據(jù)表的,需要用admin.site.register(自定義模型類) 方法進(jìn)行注冊
    • 配置步驟如下:

      1. 在應(yīng)用app中的admin.py中導(dǎo)入注冊要管理的模型models類, 如:

        from . import models
        
        
      2. 調(diào)用 admin.site.register 方法進(jìn)行注冊,如:

        from django.contrib import admin
        admin.site.register(自定義模型類)
        
        
    • 如: 在 bookstore/admin.py 添加如下代碼對Book類進(jìn)行管理

    • 示例:

      # file: bookstore/admin.py
      from django.contrib import admin
      # Register your models here.
      
      from . import models
      ...
      admin.site.register(models.Book)  # 將Book類注冊為可管理頁面
      
      

修改后臺Models的展現(xiàn)形式

  • 在admin后臺管理數(shù)據(jù)庫中對自定義的數(shù)據(jù)記錄都展示為 XXXX object 類型的記錄,不便于閱讀和判斷

  • 在用戶自定義的模型類中可以重寫 def __str__(self): 方法解決顯示問題,如:

    • 在 自定義模型類中重寫 str(self) 方法返回顯示文字內(nèi)容:
    class Book(models.Model):
        ...
        def __str__(self):
            return "書名" + self.title
    
    

模型管理器類

  • 作用:

    • 為后臺管理界面添加便于操作的新功能。
  • 說明:

    • 后臺管理器類須繼承自 django.contrib.admin 里的 ModelAdmin
  • 模型管理器的使用方法:

    1. <應(yīng)用app>/admin.py 里定義模型管理器類

      class XXXX_Manager(admin.ModelAdmin):
          ......
      
      
    2. 注冊管理器與模型類關(guān)聯(lián)

      from django.contrib import admin
      from . import models
      admin.site.register(models.YYYY, XXXX_Manager) # 注冊models.YYYY 模型類與 管理器類 XXXX_Manager 關(guān)聯(lián)
      
      
    • 示例:

      # file : bookstore/admin.py
      from django.contrib import admin
      from . import models
      
      class BookAdmin(admin.ModelAdmin):
          list_display = ['id', 'title', 'price', 'market_price']
      
      admin.site.register(models.Book, BookAdmin)
      
      
  • 模型管理器類ModelAdmin中實(shí)現(xiàn)的高級管理功能

    1. list_display 去控制哪些字段會顯示在Admin 的修改列表頁面中。
    2. list_display_links 可以控制list_display中的字段是否應(yīng)該鏈接到對象的“更改”頁面。
    3. list_filter 設(shè)置激活A(yù)dmin 修改列表頁面右側(cè)欄中的過濾器
    4. search_fields 設(shè)置啟用Admin 更改列表頁面上的搜索框。
    5. list_editable 設(shè)置為模型上的字段名稱列表,這將允許在更改列表頁面上進(jìn)行編輯。
    6. 其它參見https://docs.djangoproject.com/en/1.11/ref/contrib/admin/

數(shù)據(jù)庫表管理

  1. 修改模型類字段的顯示名字

    • 模型類各字段的第一個參數(shù)為 verbose_name,此字段顯示的名字會在后臺數(shù)據(jù)庫管理頁面顯示

    • 通過 verbose_name 字段選項(xiàng),修改顯示名稱示例如下:

      title = models.CharField(
          max_length = 30,
          verbose_name='顯示名稱'
      )
      
      
  2. 通過Meta內(nèi)嵌類 定義模型類的屬性及展現(xiàn)形式

    • 模型類可以通過定義內(nèi)部類class Meta 來重新定義當(dāng)前模型類和數(shù)據(jù)表的一些屬性信息

    • 用法格式如下:

      class Book(models.Model):
          title = CharField(....)
          class Meta:
              1. db_table = '數(shù)據(jù)表名'
                  - 該模型所用的數(shù)據(jù)表的名稱。(設(shè)置完成后需要立馬更新同步數(shù)據(jù)庫)
              2. verbose_name = '單數(shù)名'
                  - 給模型對象的一個易于理解的名稱(單數(shù)),用于顯示在/admin管理界面中
              3. verbose_name_plural = '復(fù)數(shù)名'
                  - 該對象復(fù)數(shù)形式的名稱(復(fù)數(shù)),用于顯示在/admin管理界面中
      
      
    • 示例:

      class Meta:
          db_table = 'book_table'  # 將原數(shù)據(jù)表名"bookstore_book" 換為 "book_table",請查看數(shù)據(jù)表
          verbose_name = 'booooook'
          verbose_name_plural = 'booksssssss'  # 去127.0.0.1:8000/admin下看看哪兒變化了?
      
      
  • 練習(xí):
    • 將Book模型類 和 Author 模型類都加入后臺管理
    • 制作一個AuthorManager管理器類,讓后臺管理Authors列表中顯示作者的ID、姓名、年齡信息
    • 用后臺管理程序 添加三條 Author 記錄
    • 修改其中一條記錄的年齡
    • 刪除最后一條添加的記錄
    • 將bookstore_author 數(shù)名表名稱改為myauthor (需要重新遷移數(shù)據(jù)庫)

數(shù)據(jù)表關(guān)聯(lián)關(guān)系映射 Relationship Map

  • 在關(guān)系型數(shù)據(jù)庫中,通常不會把所有數(shù)據(jù)都放在同一張表中,這樣做會額外占用內(nèi)存空間,
  • 在關(guān)系列數(shù)據(jù)庫中通常用表關(guān)聯(lián)來解決數(shù)據(jù)庫。
  • 常用的表關(guān)聯(lián)方式有三種:
    1. 一對一映射
      • 如: 一個身份證對應(yīng)一個人
    2. 一對多映射
      • 如: 一個班級可以有多個學(xué)生
    3. 多對多映射
      • 如: 一個學(xué)生可以報(bào)多個課程,一個課程可以有多個學(xué)生學(xué)習(xí)

一對一映射

  • 一對一是表示現(xiàn)實(shí)事物間存在的一對一的對應(yīng)關(guān)系。
  • 如:一個家庭只有一個戶主,一個男人有一個妻子,一個人有一個唯一的指紋信息等
  1. 語法

    在關(guān)聯(lián)的兩個類中的任何一個類中:
    class A(model.Model):
        ...
    
    class B(model.Model):
        屬性 = models.OneToOneField(A)
    
    
  2. 用法示例

    1. 創(chuàng)建作家和作家妻子類

      # file : xxxxxxxx/models.py
      from django.db import models
      
      class Author(models.Model):
          '''作家模型類'''
          name = models.CharField('作家', max_length=50)
      
      class Wife(models.Model):
          '''作家妻子模型類'''
          name = models.CharField("妻子", max_length=50)
          author = models.OneToOneField(Author)  # 增加一對一屬性
      
      
    2. 查詢

      • 在 Wife 對象中,通過 author 屬性找到對應(yīng)的author對象
      • 在 Author 對象中,通過 wife 屬性找到對應(yīng)的wife對象
    3. 創(chuàng)始一對一的數(shù)據(jù)記錄

      from . import models
      author1 = models.Author.objects.create(name='王老師')
      wife1 = models.Wife.objects.create(name='王夫人', author=author1)  # 關(guān)聯(lián)王老師
      author2 = models.Author.objects.create(name='小澤老師')  # 一對一可以沒有數(shù)據(jù)對應(yīng)的數(shù)據(jù) 
      
      
    4. 一對一數(shù)據(jù)的相互獲取

      1. 正向查詢

        • 直接通過關(guān)聯(lián)屬性查詢即可
        # 通過 wife 找 author
        from . import models
        wife = models.Wife.objects.get(name='王夫人')
        print(wife.name, '的老公是', wife.author.name)
        
        
      2. 反向查詢

        • 通過反向引用屬性查詢
        • 反向引用屬性為實(shí)例對象.引用類名(小寫),如作家的反向引用為作家對象.wife
        • 當(dāng)反向引用不存在時,則會觸發(fā)異常
        # 通過 author.wife 引用屬性 找 wife,如果沒有對應(yīng)的wife剛觸發(fā)異常
        author1 = models.Author.objects.get(name='王老師')
        print(author1.name, '的妻子是', author1.wife.name)
        author2 = models.Author.objects.get(name='小澤老師')
        try:
            print(author2.name, '的妻子是', author2.wife.name)
        except:
            print(author2.name, '還沒有妻子')
        
        
  • 作用:

    • 主要是解決常用數(shù)據(jù)不常用數(shù)據(jù)的存儲問題,把經(jīng)常加載的一個數(shù)據(jù)放在主表中,不常用數(shù)據(jù)放在另一個副表中,這樣在訪問主表數(shù)據(jù)時不需要加載副表中的數(shù)據(jù)以提高訪問速度提高效率和節(jié)省內(nèi)存空間,如經(jīng)常把書的內(nèi)容和書名建成兩張表,因?yàn)樵诰W(wǎng)站上經(jīng)常訪問書名等信息,但不需要得到書的內(nèi)容。
  • 練習(xí):

    1. 創(chuàng)建一個Wife模型類,屬性如下
      1. name
      2. age
    2. 在Wife類中增加一對一關(guān)聯(lián)關(guān)系,引用 Author
    3. 同步回?cái)?shù)據(jù)庫并觀察結(jié)果

一對多映射

  • 一對多是表示現(xiàn)實(shí)事物間存在的一對多的對應(yīng)關(guān)系。
  • 如:一個學(xué)校有多個班級,一個班級有多個學(xué)生, 一本圖書只能屬于一個出版社,一個出版社允許出版多本圖書
  1. 用法語法

    • 當(dāng)一個A類對象可以關(guān)聯(lián)多個B類對象時
    class A(model.Model):
        ...
    
    class B(model.Model):
        屬性 = models.ForeignKey(多對一中"一"的模型類, ...)
    
    
  2. 外鍵類ForeignKey

    • 構(gòu)造函數(shù):

      ForeignKey(to, on_delete, **options)
      
      
    • 常用參數(shù):

      • on_delete
        1. models.CASCADE 級聯(lián)刪除。 Django模擬SQL約束ON DELETE CASCADE的行為,并刪除包含F(xiàn)oreignKey的對象。
        2. models.PROTECT 拋出ProtectedError 以阻止被引用對象的刪除;
        3. SET_NULL 設(shè)置ForeignKey null;只有null是True才有可能。
        4. SET_DEFAULT 將ForeignKey設(shè)置為其默認(rèn)值;必須設(shè)置ForeignKey的默認(rèn)值。
        5. ... 其它參請參考文檔 https://docs.djangoproject.com/en/1.11/ref/models/fields/#foreignkey ForeignKey部分
      • **options 可以是常用的字段選項(xiàng)如:
        1. null
        2. unique等
        3. ...
  3. 示例

    • 有二個出版社對應(yīng)五本書的情況.
      1. 清華大學(xué)出版社 有書

        1. C++
        2. Java
        3. Python
      2. 北京大學(xué)出版社 有書

        1. 西游記
        2. 水滸
    1. 定義一對多類

      # file: myorm/models.py
      from django.db import models
      class Publisher(models.Model):
          '''出版社'''
          name = models.CharField('名稱', max_length=50, unique=True)
      
      class Book(models.Model):
          title = models.CharField('書名', max_length=50)
          publisher = models.ForeignKey(Publisher, null=True)
      
      
    • 創(chuàng)建一對多的對象

      # file: xxxxx/views.py
      from . import models
      pub1 = models.Publisher.objects.create(name='清華大學(xué)出版社')
      models.Book.objects.create(title='C++', publisher=pub1)
      models.Book.objects.create(title='Java', publisher=pub1)
      models.Book.objects.create(title='Python', publisher=pub1)
      
      pub2 = models.Publisher.objects.create(name='北京大學(xué)出版社')
      models.Book.objects.create(title='西游記', publisher=pub2)
      models.Book.objects.create(title='水滸', publisher=pub2)
      
      
    • 查詢:

      • 通過多查一
      # 通過一本書找到對應(yīng)的出版社
      abook = models.Book.objects.get(id=1)
      print(abook.title, '的出版社是:', abook.publisher.name)
      
      
      • 通過一查多
      # 通過出版社查詢對應(yīng)的書
      pub1 = models.Publisher.objects.get(name='清華大學(xué)出版社')
      books = pub1.book_set.all()  # 通過book_set 獲取pub1對應(yīng)的多個Book數(shù)據(jù)對象
      # books = models.Book.objects.filter(publisher=pub1)  # 也可以采用此方式獲取
      print("清華大學(xué)出版社的書有:")
      for book in books:
          print(book.title)
      
      
  • 練習(xí):
    1. 完成Book 和 Publisher 之間的一對多
    2. 查看數(shù)據(jù)庫效果
    3. 登錄到后臺,查看Book實(shí)體
  1. 數(shù)據(jù)查詢
    1. 通過 Book 查詢 Publisher

      通過 publisher 屬性查詢即可
      練習(xí):
          查詢 西游記 對應(yīng)的出版社信息,打印在終端上
      
      
    2. 通過 Publisher 查詢 對應(yīng)的所有的 Books

      Django會在Publisher中增加一個屬性來表示對對應(yīng)的Book們的查詢引用
      屬性:book_set(MyModel.objects)
      
      

多對多映射

  • 多對多表達(dá)對象之間多對多復(fù)雜關(guān)系,如: 每個人都有不同的學(xué)校(小學(xué),初中,高中,...),每個學(xué)校都有不同的學(xué)生...
  1. 語法

    在關(guān)聯(lián)的兩個類中的任意一個類中,增加:
    屬性 = models.ManyToManyField(MyModel)
    
    
  2. 示例

    一個作者可以出版多本圖書
    一本圖書可以被多名作者同時編寫
    
    class Author(models.Model):
        xxxx xxxx
    
    class Book(models.Model):
        xxxx xxxx
    
        authors = models.ManyToManyField(Author)
    
    
  3. 數(shù)據(jù)查詢

    1. 通過 Book 查詢對應(yīng)的所有的 Authors

      可以通過authors表示對應(yīng)所有Author的查詢對象
      
      book.authors.all() -> 獲取 book 對應(yīng)的所有的author的信息
      
      book.authors.filter(age__gt=80) -> 獲取book對應(yīng)的作者中年齡大于80歲的作者的信息
      
      
    2. 通過 Author 查詢對應(yīng)的所有的Books

      Django會生成一個屬性 book_set 用于表示對對應(yīng)的book的查詢對象相關(guān)操作?
      author.book_set.all()
      author.book_set.filter()
      author.book_set.create(...)  # 創(chuàng)建新書并聯(lián)作用author
      author.book_set.add(book)   # 添加已有的書為當(dāng)前作者author
      author.book_set.clear()  # 刪除author所有并聯(lián)的書
      author.book_set.remove()  # 刪除所author所有并聯(lián)的書
      
      
  4. 示例:

    • 多對多模型
    class Author(models.Model):
        '''作家模型類'''
        name = models.CharField('作家', max_length=50)
        def __str__(self):
            return self.name
    class Book(models.Model):
        title = models.CharField('書名', max_length=50)
        author = models.ManyToManyField(Author, null=True)
        def __str__(self):
            return self.title
    
    
    • 多對多視圖操作
    from django.http import HttpResponse
    
    from . import models
    
    def many2many_init(request):
        # 創(chuàng)建兩人個作者
        author1 = models.Author.objects.create(name='呂澤')
        author2 = models.Author.objects.create(name='魏老師')
    
        # 呂擇和魏老師同時寫了一本Python
        book11 = author1.book_set.create(title="Python")
        author2.book_set.add(book11)  #
    
        # 魏老師還寫了兩本書
        book21 = author2.book_set.create(title="C")  # 創(chuàng)建一本新書"C"
        book22 = author2.book_set.create(title="C++")  # 創(chuàng)建一本新書"C++"
    
        return HttpResponse("初始化成功")
    
    def show_many2many(request):
        authors = models.Author.objects.all()
        for auth in authors:
            print("作者:", auth.name, '發(fā)出版了', auth.book_set.count(), '本書: ')
            for book in books:
                print('    ', book.title)
        print("----顯示書和作者的關(guān)系----")
        books = models.Book.objects.all()
        for book in books:
            auths = book.author.all()
            print(book.title, '的作者是:', '、'.join([str(x.name) for x in auths]))
        return HttpResponse("顯示成功,請查看服務(wù)器端控制臺終端")
    
    
    • 多對多最終的SQL結(jié)果
    mysql> select * from myorm2_author;
    +----+-----------+
    | id | name      |
    +----+-----------+
    | 11 | 呂澤      |
    | 12 | 魏老師    |
    +----+-----------+
    2 rows in set (0.00 sec)
    
    mysql> select * from myorm2_book;
    +----+--------+
    | id | title  |
    +----+--------+
    | 13 | Python |
    | 14 | C      |
    | 15 | C++    |
    +----+--------+
    3 rows in set (0.00 sec)
    
    mysql> select * from myorm2_book_author;
    +----+---------+-----------+
    | id | book_id | author_id |
    +----+---------+-----------+
    | 17 |      13 |        11 |
    | 20 |      13 |        12 |
    | 18 |      14 |        12 |
    | 19 |      15 |        12 |
    +----+---------+-----------+
    4 rows in set (0.00 sec)
    
    
    • 示例示意圖 [圖片上傳失敗...(image-ed69a-1563362158182)]
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容