<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Django模型查詢與性能調優:告別N+1問題

      一、查詢基礎

      QuerySet 詳解

      Django 中通過模型類的 Manager 構建 QuerySet 來檢索數據庫對象,其核心特性包括:

      • 代表數據庫中對象的集合
      • 可通過過濾器縮小查詢范圍
      • 具有惰性執行特性(僅在需要結果時才執行 SQL)

      常用過濾器

      • all():返回所有對象
      • filter(**kwargs):返回滿足條件的對象
      • exclude(** kwargs):返回不滿足條件的對象
      • get(**kwargs):返回單個匹配對象(無匹配或多匹配會拋異常)
      • 切片
      # 切片操作示例:返回前5個對象(LIMIT 5)
      Book.objects.all()[:5]
      

      一對多關聯查詢

      假設一個作者可以寫多本書,但每本書只能屬于一個作者。

      from django.db import models
      
      class Author(models.Model):
          first_name = models.CharField(max_length=100)
          last_name = models.CharField(max_length=100)
      
          def __str__(self):
              return f"{self.first_name} {self.last_name}"
      
      class Book(models.Model):
          title = models.CharField(max_length=100)
          publication_date = models.DateField()
          # 外鍵關聯Author,級聯刪除,反向查詢名為books
          author = models.ForeignKey(
              Author, 
              on_delete=models.CASCADE, 
              related_name='books'
          )
      
          def __str__(self):
              return self.title
      

      正向查詢(通過外鍵屬性訪問)

      b = Book.objects.get(id=2)
      b.author  # 獲取關聯的Blog對象,查詢數據庫
      b.author = some_body  # 設置關聯對象
      b.save()  # 保存更改
      

      使用 select_related() 預加載關聯對象,避免額外查詢

      b = Book.objects.select_related().get(id=2)
      print(b.author)  # 已預加載到緩存,使用緩存,不查詢數據庫
      

      反向查詢(通過關聯管理器)

      # 未定義related_name, 默認Manager名稱為:<模型名稱小寫>_set
      a = Author.objects.get(id=1)
      a.book_set.all()  # 返回所有關聯的Book
      
      # 定義了related_name='books'
      a.books.all()  # 更直觀的訪問方式
      

      關聯對象操作方法如下。所有 “反向” 操作對數據庫都是立刻生效,保存到數據庫。

      • add(obj1, obj2):添加關聯對象
      • create(**kwargs):創建并關聯新對象
      • remove(obj1, obj2):移除關聯對象
      • clear():清空所有關聯
      • set(objs):替換關聯集合
      a = Author.objects.get(id=1)
      a.books.set([b1, b2]) #  b1 和 b2 都是 Book 實例
      

      多對多關聯查詢

      假設一個作者可以寫多本書,一本書也可以有多個作者。

      from django.db import models
      
      class Author(models.Model):
          name = models.CharField(max_length=100)
          email = models.EmailField()
      
          def __str__(self):
              return self.name
      
      class Book(models.Model):
          title = models.CharField(max_length=200)
          publication_date = models.DateField()
          # 多對多關聯Author
          authors = models.ManyToManyField(Author, related_name='books')
      
          def __str__(self):
              return self.title
      

      正向與反向查詢示例

      # 正向查詢
      b = Book.objects.get(id=3)
      b.authors.all() # 獲取所有關聯的Author
      b.authors.count()
      b.authors.filter(name__contains="張三")
      
      # 反向查詢
      a = Author.objects.get(id=5)
      a.book_set.all()  # 獲取所有關聯的Book
      

      多對多關聯中,add()、set() 和 remove() 可直接使用主鍵

      a = Author.objects.get(id=5)
      a.book_set.set([b1, b2])
      # 等價于
      a.book_set.set([b1.pk, b2.pk])
      

      二、N+1查詢問題

      問題分析

      N+1 查詢是常見的性能問題,表現為主查詢后執行 N 次額外查詢。例如:

      books = Book.objects.all()
      for book in books:
          print(book.author.first_name)
      

      以上代碼會產生 1 次查詢獲取所有 Book,加上 N 次查詢獲取對應的 Author(N 為 Book 數量),共 N+1 次查詢。

      檢測方法

      • Django Debug Toolbar:直觀顯示請求中的 SQL 查詢
      • 日志記錄:配置日志記錄 SQL 語句
      • 性能分析工具:如 Django Silk 分析查詢性能

      解決方案

      方法 1:使用 select_related

      適用于一對多(正向)和一對一關系,通過 SQL JOIN 預加載關聯對象

      • 語法:select_related('related_field')related_field 是模型中定義的 ForeignKeyOneToOneField 字段
      books = Book.objects.select_related('author').all()
      for book in books:
          print(book.author.first_name) # 無額外查詢 
      

      可結合 only() 選擇需要的字段

      books = Book.objects.select_related('author').only('title', 'author__name')
      

      支持多級關聯

      # 加載書籍、作者及作者家鄉信息
      books = Book.objects.select_related('author__hometown').all()
      for book in books:
          print(book.author.hometown.name)  # 無額外查詢
      

      方法 2:使用 prefetch_related

      適用于多對多和反向關系,通過批量查詢后在 Python 中關聯。適用場景:

      • 多對多關系(ManyToManyField)
      • 反向一對多關系
      • 反向一對一關系
      books = Book.objects.prefetch_related('authors').all()
      for book in books:
          print(book.authors.all())  # 無額外查詢
      

      參考資料:Django 數據庫訪問優化

      三、高級查詢優化

      values()

      返回字典形式的查詢集(返回一個 ValuesQuerySet 對象,其中每個元素是一個字典),適合提取特定字段

      books = Book.objects.values('title', 'author')
      for book in books:
          print(book) 
          
      # 輸出示例
      {'title': 'Book1', 'author': 'Author1'}
      {'title': 'Book2', 'author': 'Author2'}
      

      values_list()

      返回元組形式的查詢集(返回一個 ValuesListQuerySet 對象,其中每個元素是一個元組),內存占用更低

      books = Book.objects.values_list('title', 'author')
      for book in books:
          print(book)
          
      ### 輸出示例
      ('Book1', 'Author1')
      ('Book2', 'Author2')
      

      使用 flat=True 獲取單一字段值列表。如果有多個字段時,傳入 flat 會報錯。

      titles = Book.objects.values_list('title', flat=True)
      # <QuerySet ['紅樓夢', '西游記', ...]>
      

      使用 named=True ,結果返回 namedtuple()

      books_info = Book.objects.values_list("id", "title", named=True)
      # <QuerySet [Row(id=1, title='紅樓夢'), ...]>
      

      values()和values_list()對比

      對比維度 values() values_list()
      返回值類型 返回一個包含字典的查詢集,字典的鍵為字段名,值為字段對應的數據 返回一個包含元組的查詢集,元組中的元素依次對應指定字段的值
      內存占用 相對較高,因為字典需要存儲鍵值對信息 通常更節省內存,元組是更輕量的數據結構,無需存儲字段名
      使用場景 適合需要通過字段名訪問字段值的場景,例如需要明確知道每個值對應的字段時 適合僅需要獲取字段值的場景,例如只需批量獲取某個或某幾個字段的具體數據時

      Q() 對象復雜查詢

      Q() 對象用于構建復雜查詢條件,支持邏輯運算

      • &:邏輯與(AND)
      • |:邏輯或(OR)
      • ~:邏輯非(NOT)
      from django.db.models import Q
      
      # 標題含Python或作者為John的書籍
      books = Book.objects.filter(
          Q(title__icontains="Python") | Q(author="John")
      )
      
      # 復雜組合條件
      books = Book.objects.filter(
          (Q(title__icontains="Python") | Q(title__icontains="Django")) &
          ~Q(author="John")
      )
      

      查看生成的 SQL

      調試時可查看 QuerySet 生成的 SQL

      queryset = Book.objects.filter(author="John")
      print(queryset.query)  # 輸出對應的SQL語句
      

      四、項目實戰

      場景

      Django+Vue 后臺管理系統中,一般需要支持不同的數據權限

      • 僅本人數據權限
      • 本部門及以下數據權限
      • 本部門數據權限
      • 指定部門數據權限
      • 全部數據權限

      image-20250801113536987

      數據權限與功能權限(基于RBAC實現)的區別

      • 功能權限:控制 “能做什么”(如新增、刪除按鈕的顯示和執行)
      • 數據權限:控制 “能看到什么數據”(如銷售經理只能查看自己團隊的數據)

      實戰

      使用Q() 對象構建復雜查詢,實現靈活的數據權限計算

      image-20250801113855216

      點擊查看完整代碼


      您正在閱讀的是《Django從入門到實戰》專欄!關注不迷路~

      posted @ 2025-08-01 14:52  小王子1024  閱讀(204)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 色爱综合激情五月激情| 久久96国产精品久久久| 国产欧美另类久久久精品不卡| 人妻无码| 果冻传媒董小宛视频| 国产成人人综合亚洲欧美丁香花| 无遮挡aaaaa大片免费看| 无码人妻精品一区二区三区下载 | 宾馆人妻4P互换视频| 在线人人车操人人看视频| 久久久精品2019中文字幕之3| 精品日本乱一区二区三区| 久久国产成人高清精品亚洲| 国产日韩AV免费无码一区二区三区| 精品蜜臀国产av一区二区| 亚洲国产精品18久久久久久| 国产精品中文第一字幕| 亚洲欧美日本久久网站| 欧美成本人视频免费播放| 亚洲高潮喷水无码AV电影| 久久天天躁狠狠躁夜夜不卡| 97欧美精品系列一区二区| 万山特区| 伊人久久大香线蕉综合观| 精品一区二区三区在线播放视频| 久久亚洲私人国产精品| 成人性生交片无码免费看| 午夜精品国产自在| 免费视频一区二区三区亚洲激情| av天堂亚洲天堂亚洲天堂| 在线免费不卡视频| 亚洲a人片在线观看网址| 农村妇女野外一区二区视频| 国产精品免费中文字幕| 18禁免费无码无遮挡网站| 亚洲综合久久国产一区二区| 国产成人免费午夜在线观看| 国产成人av一区二区三区不卡| 福利一区二区1000| 国产一区二区三区高清在线观看| 综合激情网一区二区三区|