Django中是經過ORM來操做數據庫的,經過ORM能夠很easy的實現與數據庫的交互。可是仍然有幾種操做是很是繞也特別容易混淆的。因而,針對這一塊,來一個分類總結吧。python
對於ORM對數據庫的基本操做前面model裏已經有了介紹,這裏專門針對ORM的一對多、多對多、正向、反向等操做來說解用法和注意事項。sql
銘記於心的兩條:數據庫
首先來設計兩張簡單的表格,並在其中一張表中設置一個另一張表的外鍵值 django
# --*-- coding:utf-8 -*- from django.db import models class UserType(models.Model): caption = models.CharField(max_length=32) class UserInfo(models.Model): user_type = models.ForeignKey(UserType) username = models.CharField(max_length=32) age = models.IntegerField()
一、添加數據:app
傳id的方式:(字典的形式傳參)ide
user_dict = {"username": "chenchao", "age": "18", "user_type_id": 1} models.UserInfo.objects.create(**user_dict)
傳對象的方式:優化
user_type_obj = models.UserType.objects.get(id=1) #先獲取外鍵表中的數據對象 user_dict = {"username": "chenchao", "age": "18", "user_type": user_type_obj} #將對象傳入字典 models.UserInfo.objects.create(**user_dict)
講解:在咱們寫的models類時,外鍵的字段是」user_type",而django在數據庫中保存字段時默認會在後面加「_id」,因此能夠直接經過傳id的方式。idea
而在表中的外鍵字段「user_type」又表明的是字典表中的一行數據對象。因而一樣能夠傳對象的方式來傳參。spa
二、刪除數據設計
三、修改數據 (這兩個操做與上面的添加用法基本一致)
四、查找數據
正向查找:(基於存在外鍵值表的查找爲正向)
models.UserInfo.objects.filter(user_type__caption= "CEO") #查找用戶類型爲CEO的全部用戶, 雙下劃線」__「
反向查找:(基於不存在外鍵值表的查找爲反向查找,前提是兩張表已經創建了關係)
舉例:獲取某我的是什麼用戶類型?當前用戶類型下有多少人?
user_type_obj = models.UserType.objects.get(userinfo__username= "chenchao") #經過外鍵表來找到隱藏的userinfo字段下的username user_type_obj.caption # 獲取用戶chenchao的用戶類型 user_type_obj.userinfo_set.all().count() #獲取此類型下的全部用戶個數
點讚的例子:
首先設計一下數據庫表結構,使點讚的一張表與用戶和文章創建外鍵關係
class MyUser(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) def __unicode__(self): return self.username class News(models.Model): title = models.CharField(max_length=32) content = models.CharField(max_length=32) def __unicode__(self): return self.title class Favor(models.Model): user_obj = models.ForeignKey(MyUser) new_obj = models.ForeignKey(News) def __unicode__(self): return "%s -> %s" %(self.user_obj.username, self.new_obj.title)
經過反向來操做點贊表,獲取點讚的數量
def FoverNum(request): # 獲取全部文章的標題 內容和點贊數 # n_num = models.News.objects.all() # 獲取全部新聞表的數據對象 # for item in n_num: # print items.title # print items.content # print item.favor_set.all().count() # 獲取chenchao點過讚的全部的文章 all_new = models.News.objects.filter(favor__user_obj__username="chenchao") for items in all_new: print items.title print items.content print items.favor_set.all().count() return HttpResponse("Nothing")
首先設計好多對多的表結構:
class Host(models.Model): hostname = models.CharField(max_length=32) port = models.IntegerField() class HostAdmin(models.Model): username = models.CharField(max_length=32) email = models.CharField(max_length=32) host = models.ManyToManyField(Host)
前兩張表經過models就能夠建立,而第三張表django自動幫咱們建立完成。咱們主要針對第三張表,對其操做增刪改查。
一、增長數據
正向添加(基於存在外鍵值表的查找爲正向): add
user_obj = models.HostAdmin.objects.get(username="chenchao") # 獲取某個用戶的數據對象 host_obj = models.Host.objects.filter(id__lt=3) # 獲取id小於3的主機數據對象 user_obj.host.add(*host_obj) # 經過用戶對象下的ManyToMany的字段將主機與用戶的對象添加到第三張表中
反向添加:(基於不存在外鍵值表的查找爲反向查找,前提是兩張表已經創建了關係)
host_obj = models.Host.objects.get(id=1) # 一、獲取主機的數據對象 user_obj = models.HostAdmin.objects.filter(id__gt=1) # 二、獲取用戶id大於1的數據對象 host_obj.hostadmin_set.add(*user_obj) # 三、經過隱藏的外鍵字段hostadmin將主機對象與用戶對象添加到第三張表
二、查找數據
正向查找:(基於存在外鍵值的表)
user_obj = models.HostAdmin.objects.get(id=1) # 獲取用戶的數據對象 print user_obj.host.all().count() # 基於用戶對象,經過外鍵字段來查找第三張表中的個數
反向查找:(基於不存在外鍵值的表)
host_obj = models.Host.objects.get(id=1) # 獲取主機的數據對象 print host_obj.hostadmin_set.all().count() # 基於主機對象,經過隱藏的hostadmin_set字段來查找第三張中的數據
自定義Django的多對多的第三張表:
django除了能自動建立多對多的第三張表,一樣也能夠自定義建立多對多的第三張表,並且操做和管理擴展等難易程度要比自動建立的好許多。因此,在以後的models表結構中,推薦使用自定義的方式。
僅僅在建立時添加一個字段便可:through='HostRelation' 。 HostRelation是咱們自定義的第三張表名。
class Host1(models.Model): hostname = models.CharField(max_length=32) port = models.IntegerField()
class HostAdmin1(models.Model): username = models.CharField(max_length=32) email = models.CharField(max_length=32) host = models.ManyToManyField(Host1, through='HostRelation') class HostRelation(models.Model): #自定義建立第三張表,其中的外鍵都爲一對多的關係 c1 = models.ForeignKey(Host1) c2 = models.ForeignKey(HostAdmin1)
一、建立數據
操做自定義建立的多對多關係表的兩種方式:
def ManytoM(request): models.HostRelation.objects.create( # 傳對象的方式向第三張表中添加數據,笨法 c1=models.Host1.objects.get(id=1), c2=models.HostAdmin1.objects.get(id=2) ) models.HostRelation.objects.create(c1_id=2, c2_id=1,) # 傳id的方式向第三張表中添加數據,easy idea
return HttpResponse("add_many to many OK")
二、查找數據
relation_list = models.HostRelation.objects.all() # 直接經過自定義的第三張表來查找數據 for item in relation_list: print item.c1.hostname # 經過點」.「 來獲取數據 print item.c2.username print models.HostRelation.objects.filter(c2__username="chenchao") # 經過雙下劃線」__「來查找數據
select_related:用來優化數據庫查詢的操做,能夠沒有,但優化的不夠完全。
用於在foreignkey查詢的時候使用。能夠經過query來查看一下django執行的sql語句。
ret1 = models.UserInfo.objects.all() ret2 = models.UserInfo.objects.all().select_related() print ret1.query print ret2.query # 查看django執行的sql語句
ret1: SELECT "App01_userinfo"."id", "App01_userinfo"."user_type_id", "App01_userinfo"."username", "App01_userinfo"."age" FROM "App01_userinfo" ret2: SELECT "App01_userinfo"."id", "App01_userinfo"."user_type_id", "App01_userinfo"."username", "App01_userinfo"."age", "App01_usertype"."id", "App01_usertype"."caption" FROM "App01_userinfo" INNER JOIN "App01_usertype" ON ("App01_userinfo"."user_type_id" = "App01_usertype"."id")
經過sql語句咱們能夠清晰地看到select_related不只把當前表的內容查找出來,並且還把外鍵的表裏的數據也查了出來。若是咱們按ret1的方式,須要在多執行一次sql的查找操做。而ret2只須要執行一次。
若是一張表中的數字列須要增長,那麼F是最神奇的操做。
例如咱們須要把user_info表裏的全部age加1:
from django.db.models import F #先要導入F models.user_info.objects.all().update(age=F('age')+1) #執行+1
當作複雜的搜索查找條件時,django的Q能夠提供很是便利的方法。
在設計搜索條件時,相同的字段爲或操做(OR),不一樣的字段之間是且操做(AND)
from django.db.models import Q # 導入Q con = Q() # 建立Q對象 q1 = Q() q1.connector = 'OR' # q1的元素爲OR或的關係 q1.children.append(('id', 1)) q1.children.append(('id', 10)) q1.children.append(('id', 9)) q2 = Q() q2.connector = 'OR' # q2的元素爲OR或的關係 q2.children.append(('c1', 1)) q2.children.append(('c1', 10)) q2.children.append(('c1', 9)) con.add(q1, 'AND') # 將q1添加到con對象中,與其餘的Q爲且的關係 con.add(q2, 'AND') models.Tb1.objects.filter(con) #將總的Q對象添加到model的查找條件中
提示:
一、以前全部的方法 如__gt,__lt,__contains. 雙下劃線聯表查詢等等均可以繼續使用
二、append添加的是一個元組
三、最外層是用AND鏈接