django-3模型操作

from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=200)  # 書名author = models.CharField(max_length=100)  # 作者publish_date = models.DateField()  # 出版日期price = models.DecimalField(max_digits=10, decimal_places=2)  # 價格stock = models.IntegerField(default=0)  # 庫存,默認0def __str__(self):return self.title

創建對象

save

# 1. 創建實例
book = Book(title="Django 入門",author="張三",publish_date=date(2023, 1, 1),price=59.99,stock=100
)# 2. 保存到數據庫
book.save()  # 執行 INSERT 語句

create

直接創建并保存,返回創建的實例:

book = Book.objects.create(title="Python 編程",author="李四",publish_date=date(2022, 5, 10),price=49.99,stock=50
)

bulk_create

高效創建多條記錄(僅執行一次 SQL):

books = [Book(title="Java 實戰", author="王五", publish_date=date(2021, 3, 15), price=69.99, stock=30),Book(title="JavaScript 指南", author="趙六", publish_date=date(2023, 2, 20), price=55.50, stock=40)
]Book.objects.bulk_create(books)  # 批量插入

get_or_create

查詢記錄,若不存在則創建:

book, created = Book.objects.get_or_create(title="Django 入門",  # 查詢條件defaults={  # 若不存在,新增時的其他字段"author": "張三","publish_date": date(2023, 1, 1),"price": 59.99,"stock": 100}
)
# created 是布爾值:True 表示新建,False 表示查詢到已有記錄

查詢

基礎查詢

all

查詢所有記錄

all_books = Book.objects.all()

get

查詢單條記錄(必須匹配一條,否則報錯)

book = Book.objects.get(id=1)  # 通過 ID 查詢
book = Book.objects.get(title="Django 入門")  # 通過字段查詢

filter

查詢符合條件的多條記錄

# 價格大于 50 的書
expensive_books = Book.objects.filter(price__gt=50)# 作者是張三且庫存大于 0 的書
zhang_books = Book.objects.filter(author="張三", stock__gt=0)

exclude

# 排除價格小于等于 50 的書(即查詢價格 >50 的書)
cheap_books = Book.objects.exclude(price__lte=50)

高級查詢

條件表達式

  • __gt:大于(price__gt=50 → 價格 >50)
  • __lt:小于
  • __gte:大于等于
  • __lte:小于等于
  • __contains:包含(模糊查詢,區分大小寫)
  • __icontains:包含(不區分大小寫)
  • __in:在列表中(author__in=[“張三”, “李四”])
  • __range:在范圍內(publish_date__range=(start_date, end_date))
  • __isnull:是否為 null(author__isnull=True)
# 書名包含 "Django" 的書(不區分大小寫)
django_books = Book.objects.filter(title__icontains="django")# 2023 年出版的書
from datetime import date
start = date(2023, 1, 1)
end = date(2023, 12, 31)
books_2023 = Book.objects.filter(publish_date__range=(start, end))

F查詢

F() 表達式用于直接引用模型字段的值,允許在數據庫層面進行字段間的比較或運算,而無需先將數據加載到 Python 內存中。

# 示例:查詢庫存大于銷量的書籍(假設有 sales 字段)
books = Book.objects.filter(stock__gt=F('sales'))# 解釋:直接在數據庫中比較 stock 和 sales 字段,避免了 Python 層面的計算

字段運算

# 示例1:所有書籍漲價 10%
Book.objects.all().update(price=F('price') * 1.1)# 示例2:某本書庫存減少 5
book = Book.objects.get(id=1)
book.stock = F('stock') - 5
book.save()# 注意:保存后需要刷新實例才能看到最新值(因為 F() 是數據庫層面的操作)
book.refresh_from_db()  # 從數據庫重新加載數據

跨關系使用

class Author(models.Model):name = models.CharField(max_length=100)age = models.IntegerField()class Book(models.Model):title = models.CharField(max_length=200)author = models.ForeignKey(Author, on_delete=models.CASCADE)publish_year = models.IntegerField()# 示例:查詢出版年份大于作者年齡的書籍(假設作者年齡與出版年份有邏輯關聯)
books = Book.objects.filter(publish_year__gt=F('author__age'))

Q 查詢

Q() 表達式用于構建復雜的查詢條件,支持邏輯運算符(與、或、非),可以組合多個查詢條件。

|

# 示例:查詢價格大于 100 元 或 作者是 "張三" 的書籍
books = Book.objects.filter(Q(price__gt=100) | Q(author="張三")  # | 表示邏輯或
)

&

# 示例:查詢價格大于 100 元 且 作者是 "張三" 的書籍
# 等價于 filter(price__gt=100, author="張三"),但 Q() 更靈活
books = Book.objects.filter(Q(price__gt=100) & Q(author="張三")  # & 表示邏輯與
)

~

# 示例:查詢作者不是 "張三" 的書籍
books = Book.objects.filter(~Q(author="張三")  # ~ 表示邏輯非
)

嵌套使用

# 示例:查詢(價格 >100 且 2023 年出版) 或 (作者是張三且庫存 >0)的書籍
books = Book.objects.filter(Q(price__gt=100, publish_year=2023) | Q(author="張三") & Q(stock__gt=0)
)
# 等價于 Q(author="張三") & Q(price__gt=100)
books = Book.objects.filter(author="張三", Q(price__gt=100))

F () 與 Q () 結合使用

# 示例:查詢(庫存 > 銷量 且 價格 > 50) 或 (作者是張三)的書籍
books = Book.objects.filter((Q(stock__gt=F('sales')) & Q(price__gt=50)) | Q(author="張三")
)

排序與限制

order_by

# 按價格升序(默認)
books_by_price = Book.objects.order_by("price")# 按價格降序(加負號)
books_by_price_desc = Book.objects.order_by("-price")

first / last

first_book = Book.objects.first()
last_book = Book.objects.last()

reverse

反轉 QuerySet 順序(需先排序)

reversed_books = Book.objects.order_by("price").reverse()  # 等效于 order_by("-price")

切片

# 取前 10 條
top10_books = Book.objects.all()[:10]# 分頁:取第 11-20 條
page2_books = Book.objects.all()[10:20]

分組聚合

分組聚合(Group By + Aggregation)是處理統計分析類需求的強大工具,常用于計算分組數據的總和、平均值、數量等。

from django.db.models import Avg, Sum, Count# 平均價格
avg_price = Book.objects.aggregate(Avg("price"))  # {'price__avg': 58.33}# 總庫存
total_stock = Book.objects.aggregate(Sum("stock"))  # {'stock__sum': 220}# 按作者分組,統計每個作者的書籍數量
author_book_count = Book.objects.values("author").annotate(Count("id"))
# 結果:[{'author': '張三', 'id__count': 1}, {'author': '李四', 'id__count': 1}, ...]

去重計數(distinct=True)

# 統計每個作者的不同出版社數量(假設有 publisher 字段)
result = Book.objects.values('author').annotate(publisher_count=Count('publisher', distinct=True)
)

對 DateTimeField 字段,可按年、月、日等粒度分組(需結合 Trunc 函數):

from django.db.models.functions import TruncYear, TruncMonth# 按出版年份分組,統計每年出版的書籍數量
result = Book.objects.annotate(publish_year=TruncYear('publish_date')  # 提取年份
).values('publish_year').annotate(book_count=Count('id')
)# 按出版月份分組(如 2023-01, 2023-02)
result = Book.objects.annotate(publish_month=TruncMonth('publish_date')  # 提取年月
).values('publish_month').annotate(book_count=Count('id')
)

多個聚合值

# 按作者分組:統計書籍數量、平均價格、總庫存
result = Book.objects.values('author').annotate(book_count=Count('id'),avg_price=Avg('price'),total_stock=Sum('stock')
)

多字段分組 + 過濾

# 按作者和出版年份分組,統計每組書籍數量
result = Book.objects.values('author', 'publish_year').annotate(book_count=Count('id')
).order_by('author', 'publish_year')  # 按分組字段排序# 結果格式:
# [
#   {'author': '張三', 'publish_year': 2023, 'book_count': 2},
#   {'author': '張三', 'publish_year': 2022, 'book_count': 1},
#   ...
# ]

子查詢與聚合結合

# 子查詢:統計每個作者的書籍數量
author_book_count = Book.objects.filter(author=OuterRef('pk')
).annotate(count=Count('id')
).values('count')# 主查詢:查詢所有作者,并附加其書籍數量
authors = Author.objects.annotate(book_count=Subquery(author_book_count[:1])  # 取子查詢結果的第一條
)

分組后過濾(filter() 與 having 區別)

  • filter():在分組之前過濾數據(類似 SQL 的 WHERE)。
  • annotate() 后再 filter():在分組之后過濾(類似 SQL 的 HAVING)。
# 示例1:先過濾(2020年以后出版的書),再分組統計
result1 = Book.objects.filter(publish_year__gt=2020).values('author').annotate(book_count=Count('id')
)# 示例2:先分組,再過濾分組結果(只保留書籍數量 > 2 的作者)
result2 = Book.objects.values('author').annotate(book_count=Count('id')
).filter(book_count__gt=2)  # 此處 filter 等效于 HAVING book_count > 2

對關聯模型(如外鍵、多對多)進行分組聚合時,需通過雙下劃線(__)關聯字段。

class Author(models.Model):name = models.CharField(max_length=100)country = models.CharField(max_length=50)  # 作者所屬國家class Book(models.Model):title = models.CharField(max_length=200)author = models.ForeignKey(Author, on_delete=models.CASCADE)  # 外鍵關聯作者price = models.DecimalField(max_digits=10, decimal_places=2)
# 按作者的國家分組,統計每個國家的書籍總數和平均價格:
from django.db.models import Count, Avgresult = Book.objects.values('author__country').annotate(total_books=Count('id'),avg_book_price=Avg('price')
)# 結果格式:
# [
#   {'author__country': '中國', 'total_books': 10, 'avg_book_price': 55.5},
#   {'author__country': '美國', 'total_books': 8, 'avg_book_price': 62.3},
#   ...
# ]
常用聚合函數
  • Count
  • Sum
  • Avg
  • Max
  • Min
  • StdDev: 標準差(僅部分數據庫支持)
  • Variance: 方差(僅部分數據庫支持)

values

返回字典列表(鍵為字段名)。

# 獲取所有書籍的標題和作者
book_data = Book.objects.values('title', 'author__name')
# 結果:[{'title': 'Django 入門', 'author__name': '張三'}, ...]

values_list

# 獲取所有書籍標題(扁平列表)
titles = Book.objects.values_list('title', flat=True)
# 結果:['Django 入門', 'Python 編程', ...]

only

僅加載指定字段(其他字段訪問會觸發新查詢)。

# 只加載書名和作者(適合列表展示等場景)
books = Book.objects.only('title', 'author__name')

defer

延遲加載指定字段(與 only 相反)。

# 不加載大文本字段 content(適合不需要展示詳情的場景)
books = Book.objects.defer('content')

select_related

select_related:用于外鍵 / 一對一關系,通過 JOIN 一次性加載關聯對象(適用于 “單對象” 關聯)。

# 普通查詢(會產生 N+1 條 SQL:1 條查書籍,N 條查對應作者)
books = Book.objects.all()
for book in books:print(book.author.name)  # 每次訪問 author 都會觸發新查詢# 優化后(僅 1 條 SQL,通過 JOIN 加載書籍和關聯的作者)
books = Book.objects.select_related('author').all()
for book in books:print(book.author.name)  # 無額外查詢

prefetch_related

用于多對多 / 反向外鍵關系,通過單獨查詢關聯對象再在 Python 中關聯(適用于 “多對象” 關聯)。

# 優化多對多查詢(書籍與標簽)
books = Book.objects.prefetch_related('tags').all()
for book in books:print([tag.name for tag in book.tags.all()])  # 無額外查詢
# 加載書籍、作者及其所有作品
books = Book.objects.select_related('author').prefetch_related('author__books').all()

原始 SQL 查詢

raw

raw(sql, params=None):執行原始 SQL 并返回模型實例

books = Book.objects.raw("SELECT * FROM myapp_book WHERE price > %s", [50])

extra()

附加 SQL 片段(不推薦,建議用 annotate 或 F/Q)

books = Book.objects.extra(where=["price > 50"])

QuerySet 基本特性

QuerySet 是 Django ORM 中用于與數據庫交互的核心對象,它代表數據庫中一組記錄的集合,支持鏈式操作和延遲執行。

延遲執行(Lazy Evaluation)

QuerySet 不會立即執行數據庫查詢,直到真正需要使用數據時才會觸發 SQL 執行。這是 QuerySet 最核心的特性之一。

# 定義 QuerySet(未執行查詢)
books = Book.objects.filter(author="張三")# 以下操作會觸發 SQL 執行:
print(books)  # 打印時
for book in books:  # 迭代時pass
list(books)  # 轉換為列表時
if books:  # 判斷布爾值時

可鏈式調用

# 鏈式調用:價格大于 50 且 2023 年出版的書,按價格降序
books = Book.objects.filter(price__gt=50).filter(publish_year=2023).order_by("-price")

不可變對象

QuerySet 是不可變的,每次鏈式調用都會返回一個新的 QuerySet,原 QuerySet 不會被修改:

qs1 = Book.objects.filter(author="張三")
qs2 = qs1.filter(price__gt=50)  # qs1 不變,qs2 是新的 QuerySet
復制 QuerySet

由于 QuerySet 是不可變的,可通過 all() 復制:

qs1 = Book.objects.filter(author="張三")
qs2 = qs1.all()  # 復制 qs1,后續操作不影響 qs1

QuerySet 與其他對象的區別

在這里插入圖片描述

更新數據

save

單個實例更新

# 1. 查詢實例
book = Book.objects.get(id=1)# 2. 修改字段
book.price = 65.99  # 漲價
book.stock -= 1  # 庫存減1# 3. 保存到數據庫
book.save()  # 執行 UPDATE 語句

update

# 所有張三的書漲價 10%
Book.objects.filter(author="張三").update(price=F("price") * 1.1)
# 注意:F() 用于引用字段本身,避免先查詢再計算的競態問題

bulk_update

# 1. 查詢需要更新的實例
books = Book.objects.filter(author="張三")# 2. 修改實例字段
for book in books:book.stock += 5  # 庫存各加5# 3. 批量更新(指定需要更新的字段)
Book.objects.bulk_update(books, ["stock"])

條件更新與 Case/When

from django.db.models import Case, When, IntegerField# 對不同書籍設置不同庫存
Book.objects.update(stock=Case(When(title__icontains="Django", then=100),  # Django 相關書籍庫存設為 100When(author="張三", then=50),  # 張三的書庫存設為 50default=0,  # 其他默認 0output_field=IntegerField())
)

刪除

book = Book.objects.get(id=1)
book.delete()  # 執行 DELETE 語句# 刪除所有庫存為 0 的書
Book.objects.filter(stock=0).delete()
  • 刪除操作不可逆,謹慎使用。
  • 若模型設置了 on_delete 關聯關系(如外鍵),刪除時會觸發對應的級聯行為(如 CASCADE 級聯刪除)。

其他操作

iterator

適合大數據量,減少內存占用(一次加載一批)

# 處理 100 萬條記錄,每次加載 1000 條
for book in Book.objects.iterator(chunk_size=1000):process(book)

refresh_from_db

刷新實例(從數據庫重新加載)

book = Book.objects.get(id=1)
# 其他操作可能修改了數據庫中的記錄...
book.refresh_from_db()  # 從數據庫重新加載最新數據

count

# 總書籍數量
total = Book.objects.count()# 張三的書籍數量
zhang_count = Book.objects.filter(author="張三").count()

exists

# 判斷是否有價格大于 100 的書
has_expensive = Book.objects.filter(price__gt=100).exists()  # 返回布爾值

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91493.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91493.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91493.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【繪制圖像輪廓】——圖像預處理(OpenCV)

目錄 1 什么是輪廓 2 尋找輪廓 2.1 mode參數 2.2 method參數 3 繪制輪廓 1 什么是輪廓 輪廓是一系列相連的點組成的曲線,代表了物體的基本外形。輪廓是連續的,邊緣不一定連續。輪廓是一個閉合的、封閉的形狀。 輪廓的作用: 形狀分析 目…

嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版)

嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版) 目錄嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版)第一章 嵌入式 Linux 基礎概念1.1 定義與核心特征1.2 典型架構棧深度解析第二章 Linux 文件…

xcode swift項目運行、連接真機運行報錯,引入文件夾失敗

最近亂七八糟解決了很多報錯,看著記錄點吧 xcode版本:16 failed to emit precompiled header ‘/Users/yuqing/Library/Developer/Xcode/DerivedData/cloudspace-ios-ejldldcfhouqnretchuzoewmsqkg/Build/Intermediates.noindex/PrecompiledHeaders/spic…

[python][selenium] Web UI自動化8種頁面元素定位方式

測試工程師必備!Selenium自動化測試全攻略 | 手寫POM框架數據驅動,輕松搞定UI自動化!簡單的加個前置知識: 第一:webdriver.Chrome()這句話,通過WebDriver的構造方法,拿到瀏覽器驅動的對象&…

絲桿支撐座在電子裝配中的關鍵作用

絲桿支撐座是電子裝配過程中不可或缺的組件,主要用于支撐和固定絲桿,確保其穩定性和精度。在高速、高精度裝配場景中,絲桿支撐座的作用尤為突出。穩定性與精度保障:絲桿支撐座采用高品質鋼材制作,具有高剛性和高強度&a…

微信小程序頁面間通信的實現方式

微信小程序中頁面間的通信是指不同頁面之間的數據傳遞、狀態同步或交互操作,常見于多頁面協作場景。根據通信方向和場景不同,主要有以下幾種實現方式:一、基于頁面跳轉的參數傳遞1. 正向傳遞(A頁面到B頁面)通過URL參數…

uniapp開發微信小程序(新舊版本對比:授權手機號登錄、授權頭像和昵稱)

目錄標題授權手機號新舊版本核心差異對比強制使用新版的情況代碼實現方案特殊處理邏輯企業賬號要求最佳實踐建議授權頭像和昵稱新舊版本核心差異對比強制使用新版的情況代碼實現方案最佳實踐建議注意事項授權手機號 新舊版本核心差異對比 觸發方式 舊版(2023年前&…

Java函數式編程之【Stream終止操作】【下】【三】【收集操作collect()與分組分區】【下游收集器】

分組收集器groupingBy():groupingBy()收集器用于按條件對元素象進行分組,并將結果存儲在Map實例中。其作用與數據庫的SQL語句的group by的用法有異曲同工之妙。 分區收集器partitioningBy():partitioningBy()可以看作是分組groupingBy()的特殊…

python設計模式-工廠模式

工廠模式的核心思想:封裝對象創建過程、解耦對象使用與創建 。示例代碼:from enum import Enum# 基類:人類 class Person:species Homo sapiensdef __init__(self, name):self.name namedef __str__(self):return f"{self.__class__._…

Rust:anyhow::Result 與其他 Result 類型轉換

當函數返回的不是 anyhow::Result 而是其他 Result 類型時(如 std::io::Result、serde_json::Result 或自定義 Result),可通過以下方法統一處理錯誤類型,確保與 anyhow 兼容或實現錯誤傳播:🛠? 一、錯誤類…

PLC-梯形圖編程

1.位運算,比較 如&#xff1a;>,<,, 2.定時器 生成脈沖TP&#xff0c;常開觸點閉合觸發&#xff0c;賦值10秒時長&#xff0c;PT配置參數&#xff0c;ET運行時已PT計時 接通延時TON&#xff0c;常開觸點閉合觸發&#xff0c;延時10秒后賦值 關斷延時TOF&#xff0c;常開觸…

LLM學習筆記5——InstructGPT

系列文章目錄 參考文獻 參考文獻 參考文獻 參考視頻 文章目錄系列文章目錄前言目前大模型不同的技術流派與框架路線&#xff1a;1. ??BERT&#xff1a;Encoder-only架構????1&#xff09; 架構特點????2&#xff09; 訓練目標??3&#xff09; ????應用場景2. …

熱能小車cad【12張】三維圖+設計說明書

摘要 無碳小車來自全國大學生工程能力訓練大賽題目&#xff0c;根據“節能減排&#xff0c;綠色出行”的環保理念&#xff0c;提出了一種基于熱力驅動的具有方向自動控制的無碳小車。 本文設計的無碳小車主要是將熱能轉化成機械能&#xff0c;用來驅動小車前進的裝置&#xff0…

云原生 DevOps 實戰之Jenkins+Gitee+Harbor+Kubernetes 構建自動化部署體系

技術背景? 在云原生生態中&#xff0c;工具鏈的選擇直接決定 CI/CD 流水線的效率與穩定性。本次方案的工具組合并非偶然&#xff0c;而是基于各組件的核心優勢與生態適配性&#xff1a;? 代碼管理層&#xff1a;Gitee 作為國內主流的代碼托管平臺&#xff0c;支持 Git 分布…

二建機電工程專業都考哪些知識點?

二建機電工程專業需要考《建設工程施工管理》《建設工程法規及相關知識》和《機電工程管理與實務》三個科目。其中《機電工程管理與實務》是專業科目&#xff0c;也是考試重點&#xff0c;主要考查機電工程技術、機電工程相關法規與標準、機電工程項目管理實務等內容。具體如下…

React + ts + react-webcam + CamSplitter 實現虛擬攝像頭解決win攝像頭獨占的問題

一、安裝 CamSplitter 這塊網上有很多教程了&#xff0c;這里不再贅述&#xff0c;就一點&#xff0c;需要分幾個虛擬攝像頭&#xff0c;就要在CamSplitter 的安裝目錄下 driver_install.cmd 執行幾次。二、React ts react-webcam 調用虛擬攝像頭import { useState, useEffec…

【深度學習①】 | Numpy數組篇

0 序言 本文為NumPy數組庫的系統學習筆記&#xff0c;將自己先前的筆記做一個總結歸納。內容涵蓋數組基礎、創建、索引、變形、運算、函數、布爾型數組及與張量的銜接等內容。通過具體示例解析核心概念與操作&#xff0c;幫助讀者掌握NumPy的使用邏輯與方法&#xff0c;為后續深…

5.實現 call

call 是 JavaScript 中非常核心的函數方法之一。它能改變函數的執行上下文&#xff08;也就是 this 的指向&#xff09;&#xff0c;在日常開發和面試中都極其常見。本文將帶你一步步實現一個 Function.prototype.call 的自定義版本&#xff0c;真正理解它的底層原理。? 一、c…

Go語言中的盲點:競態檢測和互斥鎖的錯覺

&#x1f9e0; Go語言中的盲點&#xff1a;競態檢測和互斥鎖的錯覺 使用 -race 就能發現所有并發問題&#xff1f;加了 mutex 就萬無一失&#xff1f; 這篇文章揭示了 Go 并發編程中的一個“危險盲區” —— 互斥鎖并不能總能保護你免受數據競爭的影響&#xff0c;尤其是在 -ra…

從文件到文件描述符:理解程序與文件的交互本質

一、理解文件 拋一個概念&#xff1a; 文件 內容 屬性。 1. 那么&#xff0c;空文件有大小嗎&#xff1f;答案是有的。因為空文件指的是文件內容為空&#xff0c;文件屬性也要占據大小啊。 將來對文件操作&#xff0c;無非分為兩類&#xff1a; 1.對文件內容做修改。 2.對文件…