Python DJango ORM操作
這篇來紀錄一下Python DJango ORM的相關操作。
資料的建立
TABLE_NAME.objects.create(colume1='xxx', colume2='yyy', colume3='zzz')
資料的讀取
#使用預設DB存取表格的方式
TABLE_NAME.objects.all()
#使用非預設DB存取表格的方式
TABLE_NAME.objects.using(DB_NAME).all()
DB_NAME:settings.py中其他定義的資料庫名稱
TABLE_NAME:資料表格的名稱
#回傳符合條件的唯一一筆資料。如果找不到符合條件的資料、或是有多筆資料符合條件,都會產生 exception。
TABLE_NAME.objects.get(pk=123)
#透過filter來進行資料篩選
#bkname這個欄位包含「XYZ」的資料列
TABLE_NAME.objects.filter(bkname__contains='XYZ')
#bkname這個欄位是「XYZ」的資料列
TABLE_NAME.objects.filter(bkname='XYZ')
#bkname這個欄位不是「XYZ」的資料列
TABLE_NAME.objects.exclude(bkname='XYZ')
#排序。透過加上「-」可達到desc的效果
TABLE_NAME.objects.order_by('-column_name')
#排序,且只抓10筆
TABLE_NAME.objects.order_by('-column_name')[:10]
資料的修改
bkn = TABLE_NAME.objects.filter(bkname__contains='XYZ')
bkn.update(colume1='aaa')
資料的刪除
bkn = TABLE_NAME.objects.filter(bkname__contains='XYZ')
bkn.delete()
DJango ORM下的JOIN
理解dajngo ORM查询中select_related的作用_Nick_Spider的博客-CSDN博客_select_related
select_related
select_related 將會根據外鍵關係(注意: 僅限一對一和多對一關係),在執行查詢語句的時候通過建立一個包含 SQL inner join 操作的 SELECT 語句來一次性獲得主對象及相關對象的資料。且透過指定的結果,可以避免重複的對資料庫進行存取。
以下面的範例為例,有兩個表格「Job」與「Project」,其中Project透過job這個foreign key對應到表格Job。如果Job表格中有n筆資料,Project表格中有m筆資料,需要透過Project表格的查詢來印出Job的job_name時,透過<作法1>僅需使用約2次的SQL查詢次數,透過<作法2>則會需要約 m +1 次的SQL查詢次數。當層數越多的時候,造成的影響就越可觀。
透過<作法1>,在列印 item.job.job_name 時會從qs1的緩存結果中直接搜尋;透過<作法2>,在列印 item.job.job_name時,for迴圈中會不斷的驅動一次新的SQL查詢。
# ========== models.py ==========
class Person(models.Model):
person_number = models.CharField(max_length=20, primary_key=True)
person_name = models.CharField(max_length=50, blank=True, null=True)
class Employee(models.Model):
person = models.ForeignKey(Person, null=True) # updated (null=True)***
employee_number = models.CharField(max_length=50, blank=True, null=True)
class Company(models.Model):
company_name = models.CharField(max_length=50, blank=True, null=True)
employee = models.ForeignKey(Employee, null=True) # updated (null=True)***
# ========== views.py ==========
#作法1
qs1 = Company.objects.select_related('employee')
for item in qs1:
print(item.employee.employee_number)
#作法2
qs2 = Company.objects
for item in qs2:
print(item.employee.employee_number)
select_related 中透過「__」來實現兩層的外鍵連接
qsperson = Company.objects.select_related('employee__person')
qsperson = Company.objects.select_related('employee__person').filter(company_name='FIH')
以下是網路上查到的一些相關注意事項
- 主要針一對一和多對一關係進行優化。
- 可以通過可變長參數指定需要select_related的欄位名。
- 沒有指定的欄位不會緩存,沒有指定的深度不會緩存,如果要訪問的話Django會再次進行SQL查詢。
- 可以通過depth參數指定遞歸的深度,Django會自動緩存指定深度內所有的欄位。 如果要訪問指定深度外的字段,Django會再次進行SQL查詢。
- 也接受無參數的調用,Django會盡可能深的遞歸查詢所有的字段。 但注意有Django遞歸的限制和性能的浪費。
- Django >= 1.7,鏈式調用的select_related相當於使用可變長參數。 Django < 1.7,鏈式調用會導致前邊的select_related失效,只保留最後一個。
select_related('foo', 'bar')
is equivalent toselect_related('foo').select_related('bar')
.- The order of
filter()
andselect_related()
chaining isn’t important. These querysets are equivalent:
[筆記] Django Query 優化. 最近處理的 server 有個 api… | by Lin Po-An | Medium
Django之ORM跨表查询、join查询、聚合查询、分组查询_Sunny_Future的博客-CSDN博客_django join查询