Django的對象關系映射系統(Object-Relational Mapper, ORM)提供了豐富的數據查詢接口, 讓你無需使用原生SQL語句即可通過對模型的簡單操作實現對數據庫里的數據進行增刪改查。查詢得到的結果叫查詢集(QuerySet), 所以這個接口被稱為QuerySet API。今天我們就以博客blog為例,演示下Django是如何通過模型對數據庫進行增刪改查的
Article模型如下所示:
from django.db import models class Article(models.Model): title = models.CharField('標題', max_length=200, unique=True) body = models.TextField('正文') created = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
新增
Django提供了兩種方法,save()
和create()
方法
方法一:save方法
from .models import Article article = Article(title="My first article", body="My first article body") article.save()
注意: 該方法如果不主動選擇save(), 創建的對象實例只會存於內存之中,不會保存到數據庫中去。正因為如此,Django還提供了更便捷的create方法
方法二:create方法
article = Article.objects.create(title="My first article", body="My first article body")
為了避免重復創建數據表中已存在的條目,Django還提供了get_or_create
方法。它會返回查詢到的或新建的模型對象實例,還會返回這個對象實例是否是剛剛創建的
obj, created = Article.objects.get_or_create(title="My first article", body="My first article body")
使用了save和create方法,再次請求時,是如下返回:
使用get_or_create方法的返回是:
但實際上也是不會往數據庫寫入數據的
方法三:bulk_create方法
在Django中向數據庫中插入多條數據時,每使用save或create方法保存一條就會執行一次SQL。而Django提供的bulk_create
方法可以一次SQL添加多條數據,效率要高很多,如下所示
# 內存生成多個對象實例 articles = [Article(title="title1", body="body1"), Article(title="title2", body="body2"), Article(title="title3", body="body3")] # 執行一次SQL插入數據 Article.objects.bulk_create(articles)
刪除
刪即從數據表中刪除一個已有條目。Django也允許同時刪除一條或多條數據
刪除單條數據
# 刪除第1篇文章 Article.objects.get(pk=1).delete()
刪除部分數據
# 刪除標題含有python的文章 Article.objects.filter(title__icontains="python").delete()
刪除所有數據
# 慎用 Article.objects.all().delete()
修改
改既可以用save方法,也可以用update方法。其區別在於save方法不僅可以更新數據中現有對象數據,還可以創建新的對象。而update方法只能用於更新已有對象數據。一般來說,如果要同時更新多個對象數據,用update方法或bulk_update方法更合適
方法一: save方法
article = Article.objects.get(id=1) article.title = "New article title" article.save()
方法二:update方法更新單篇文章
article = Article.objects.get(id=1).update(title='new title')
此方法未試成功
方法三:update方法同時更新多篇文章
# 更新所有文章標題 article = Article.objects.filter(title__icontains='python').update(title='Django')
方法四: bulk_update方法
與bulk_create
方法類似,Django還提供了bulk_update
方法可以對數據庫里的數據進行批量更新
查
查主要使用get, filter及exclude方法,而且這些方法是可以聯用的
# QuerySet類型,實例對象列表 Article.objects.all() # 字典列表 Article.objects.all().values() # 只獲取title-字典形式 Article.objects.all().values('title') # 只獲取title列表- 元組形式,只有value,沒有key Article.objects.all().values_list('title') # 只獲取title列表,只有value Article.objects.all().values_list('title', flat=True)
當上述查詢有個問題,如果id不存在,會拋出錯誤。還有一種方式是使用filter
方法, 這樣即使id不存在也不會報錯
article = Article.objects.filter(id=1).first()
一個更好的方式是使用Django提供的get_object_or_404
方法,如下所示
from django.shortcuts import get_object_or_404 article = get_object_or_404(Article, pk=1)
查詢多條數據
按大於、小於及不等於查詢
# gte:大於等於,lte:小於等於 articles = Article.objects.filter(id__gte=2).filter(id__lte=11) # 不等於 articles = Article.objects.exclude(id=10)
按范圍查
# 按范圍查詢,in或者range articles = Article.objects.filter(id__range=[2, 11]) articles = Article.objects.filter(id__in=[3, 6,9])
字符串模糊查詢
#標題包含python,若忽略大小寫使用icontains articles = Article.objects.filter(title__contains='python') #標題以python開頭,若忽略大小寫使用istartswith articles = Article.objects.filter(title__startswith='python') #標題是python結尾的,若忽略大小寫使用__iendswith articles = Article.objects.filter(title__endswith='python')
按日期時間查詢
# 查詢2021年發表的文章 Article.objects.filter(created__year=2021) # 查詢2021年3月19日發表的文章 import datetime Article.objects.filter(created__date=datetime.date(2021,3,19)) # 查詢2021年1月1日以后發表的文章 Article.objects.filter(created__gt=datetime.date(2021, 1, 1)) # 與當前時間相比,查詢即將發表的文章 from django.utils import timezone Article.objects.filter(created__gt=timezone.now()) # 按絕對時間范圍查詢,查詢2021年1月1日到6月30日發表文章 article = Aritlce.objects.filter(created__gte=datetime.date(2021, 1, 1), pub_date__lte=datetime.date(2021, 6, 30)) # 按相對時間范圍查詢,用range查詢3月1日以后30天內發表文章 startdate = datetime.date(2021, 3, 1) enddate = startdate + datetime.timedelta(days=30) Article.objects.filter(pub_date__range=[startdate, enddate])
切片、排序、去重
# 切片 articles = Article.objects.filter(created__year=2021)[:5] # 排序:created正序,-表示逆序 articles = Article.objects.all().order_by('-created') # 去重 Article.objects.filter(title__icontains='python').distinct()
高級Q和F方法
Q方法
有時候我們需要執行or邏輯的條件查詢,這時使用Q方法就可以了,它可以連接多個查詢條件。Q對象前面加~可以表示否定
from django.models import Q # 查詢標題含有python或Django的文章 article = Article.objects.filter(Q(title__icontains='python')|Q(title__icontains='django')) # 查詢標題含有python,不含有Django的文章 article = Article.objects.filter(Q(title__icontains='python')|~Q(title__icontains='django'))
F方法
使用F()
方法可以實現基於自身字段值來過濾一組對象,它還支持加、減、乘、除、取模和冪運算等算術操作
from django.db.models import F Article.objects.filter(n_commnets__gt=F('n_pingbacks')) Article.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
小結
我們介紹了Django中常用的模型查詢API,並以博客為例介紹了如何使用基本語句對數據庫里的數據進行增刪改查。
參考博客