Django基礎——Model篇(二)

一 Model連表關係

     一對多:models.ForeignKey(其餘表)
    多對多:models.ManyToManyField(其餘表)
    一對一:models.OneToOneField(其餘表)
    通常在數據庫中建立外鍵關聯時,就有一對多或者多對多,而一對一是Django獨有的。html

應用場景:
    一對多:當一張表中建立一行數據時,有一個單選的下拉框(下拉框中內容,可被重複選擇)
    例如:建立用戶信息時,須要選擇一個用戶類型:普通用戶、金牌用戶、鉑金用戶等。
    
    多對多:在某表中建立一行數據時,有一個能夠多選的下拉框
    例如:建立用戶信息時,須要爲用戶選擇多個愛好
    
    一對一:在某表中建立一行數據時,有一個單選的下拉框(下拉框中內容只能被選擇1次)
    例如:原有含10列數據的一張表保存相關信息,通過一段時間以後,10列沒法知足需求,須要爲原來的表再添加5列數據
前端

 1 一對多python

   一對多表結構是爲了解決空間浪費問題,經過一張數據庫表去關聯另一張數據庫表來解決重複出現的字段,這樣在這張表中只會存儲相應的ID來代替相應的字段。數據庫

                          

    爲何是1對多呢?由於在第2張表裏,金牌會員的ID=3,而在第3張表裏有好2個3,即表示1對多。django

    在Model中生成一對多表結構(models.py文件) app

    例1:第1種一對多(默認關聯id)函數

# 用戶類型類
class UserType(models.Model): user_type = models.CharField(max_length=64) #用戶信息類
class UserInfo(models.Model): username = models.CharField(max_length=64) email = models.CharField(max_length=32) # 外鍵關聯 usertype對應着UserInfo表中的1列數據,他自動關聯了UserType類
     usertype = models.ForeignKey(UserType)

    例2:第2種一對多(指定關聯字段)post

# 業務線類
class Business(models.Model):
#設置爲主鍵 nid
= models.AutoField(primary_key=True) name = models.CharField(max_length=32) # 主機類,表示主機屬於哪一條業務線 class Host(models.Model): hostname = models.CharField(max_length=16) # 括號中的參數可加引號,也能夠不加引號,效果同樣,to_field參數表示關聯哪一個字段 business = models.ForeignKey(Business,to_field='nid')

   例3:第3種一對多(多級外鍵關聯)測試

#一對多 多級外鍵關聯
class A(models.Model): name = models.CharField(max_length=16) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=32) obj_a = models.ForeignKey(A) def __unicode__(self): return self.caption class User(models.Model): username = models.CharField(max_length=32) user_group = models.ForeignKey(UserGroup) def __unicode__(self): return self.hostname

 2 多對多spa

    在Zabbix監控中會存在用戶與用戶組的概念,在這裏同一我的能夠屬於多個用戶組,同時同一個用戶組也能夠包括多我的。在這個場景中一對多的表關係結構是不能解決這個問題的,從而引出了多對多的概念。

                                      

    爲何是多對多呢?由於在對於CEO組,有兩我的,即1個組包括了多我的;同時對於alex,他分別屬於兩個不一樣組,那麼認爲這種關係就是多對多。

    在Model中生成多對多表結構(models.py文件)

# model中的多對多 # 應用場景:用戶與用戶組(一個用戶能夠在多個組,同時一個組能夠同時存在多個用戶)
class UserGroup(models.Model): group_name = models.CharField(max_length=16) class User(models.Model): name = models.CharField(max_length=16) email = models.CharField(max_length=16) mobile = models.CharField(max_length=16) # 兩張表創建多對多,django默認會生成一張數據庫表來創建二者的關係
    relationship = models.ManyToManyField(UserGroup)

     注:對於多對多,在models.py中咱們只寫了兩個類,即生成兩張數據庫表,但兩張代表顯不能很好的表示多對多的關係,在這種狀況下Django默認爲咱們生成另一張表來創建這種關係,即用3張表來表示用戶和用戶組之間的關係。

  3 一對一

   一對一不是數據庫的連表結構,而是Django獨有的,他是在一對多的基礎僞造出來的。即在一對多中限定某個指定的字段不能重複,一旦重複數據庫報錯,這樣就至關於構造了一個一對一的連表關係。在上述一對多中,用戶級別是可重複的,但在一對一關係中,一個用戶級別只能對應一個用戶,不容許重複。

   應用場景:假設在一個公司的全部用戶中,只有alex和eric能夠登陸後臺管理,那麼這個場景就可使用一對一的連表關係。

                                      

   在Model中生成一對一表結構(models.py文件)

# model中的一對一,至關於對一對多進行限制後產生的,由Django完成,且是Django獨有的 # 應用場景:在不少用戶中只有某些用戶可以登陸,這時id不能重複,即同一個帳號ID不能出現屢次 # 下表爲全部的用戶信息表
class User(models.Model): name = models.CharField(max_length=16) email = models.CharField(max_length=16) mobile = models.CharField(max_length=16) # 下表爲可以登陸的用戶的用戶名和密碼
class admim(models.Model): username = models.CharField(max_length=64) password = models.CharField(max_length=64) # django自動完成關係的創建
    user_info = models.OneToOneField(User)

 二 Model連表操做(了不得的雙下劃線)

 1 一對多連表操做

 實例1:在頁面建立用戶,同時在頁面進行展現

 models.py文件

#-*- coding:utf-8 -*-

from __future__ import unicode_literals from django.db import models #一對多連表關係 #用戶組表
class UserGroup(models.Model): caption = models.CharField(max_length=32) def __unicode__(self): return self.caption #用戶表
class User(models.Model): username = models.CharField(max_length=32)
#user_group爲對象,對應UserGroup中的一行數據 user_group
= models.ForeignKey(UserGroup) def __unicode__(self): return self.hostname

 forms模塊中的foreign.py文件

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django import forms from app01 import models class UserForm(forms.Form): # 建立用戶名
    username = forms.CharField() # 建立用戶組的兩種方法
    
    # 第1種方法:
    # group = forms.IntegerField(widget=forms.Select())
    
    # 第2種方法:用戶組字段名=models.py中User類的用戶組字段名+"_id"
    # 由於外鍵user_group字段在User數據庫表中字段名默認變成了"user_group_id",這樣作的好處:username和user_group_id直接組成字典
    # 傳給Model,由於Model建立數據時是接受字典形式參數的,就是views/foreign.py中的all_data
    user_group_id = forms.IntegerField(widget=forms.Select()) def __init__(self,*args,**kwargs): # 執行父類的構造方法
        super(UserForm,self).__init__(*args,**kwargs) # 配合建立用戶組的第1種方法使用,這裏同時注意values_list方法的使用
        # self.fields['group'].widget.choices = models.UserGroup.objects.all().values_list('id','caption')
        
        # 配合建立用戶組的第2種方法使用
        self.fields['user_group_id'].widget.choices = models.UserGroup.objects.all().values_list('id','caption')

 views模塊中foreign.py文件

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django.shortcuts import HttpResponse,render from app01 import models from app01.forms import foreign as ForeignForm # 建立用戶組表
def create_user_group(request): # 建立用戶組的類型,運行一次後註釋,防止屢次生成
    # models.UserGroup.objects.create(caption='CEO')
    # models.UserGroup.objects.create(caption='CTO')
    # models.UserGroup.objects.create(caption='COO')
    return HttpResponse('ok') # 建立用戶表
def create_user(request): # 將請求數據做爲參數傳遞給UserForm,生成相應對象
    obj = ForeignForm.UserForm(request.POST) # 判斷請求類型是否爲'POST'類型
    if request.method == 'POST': # 進行From表單驗證,驗證其有效性
        if obj.is_valid(): # 獲取請求數據
            all_data = obj.clean() # 把獲取的數據存儲到數據庫,有3種方法
            # 第1種方法(對象級別操做):先獲取對象
            # group_obj = models.UserGroup.objects.get(id=all_data['group'])
            # 爲何建立數據庫表時,第二個參數(關聯外鍵)user_group=group_obj?
            # 這是由於在Model裏user_group = models.ForeignKey('UserGroup'),這裏user_group其實是關聯了一個對象,
            # 因此在傳遞參數時要傳遞相應的對象參數。
            # models.User.objects.create(username=all_data['username'],user_group=group_obj)

            # 第2種方法(數據庫級別操做,這裏注意Django默認給外鍵字段名加上了"_id")
            # models.User.objects.create(username=all_data['username'],user_group_id=all_data['group'])
            
            # 第3種方法(傳字典參數,可是要注意form中已經組成了字典數據)
            models.User.objects.create(**all_data) # 打印數據庫中因此信息的條數
            print models.User.objects.all().count() else: # 寫上報錯提示信息,form表單的驗證信息,這裏省略了
            pass
            
    # 獲取全部的用戶信息列表
    user_list = models.User.objects.all() return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})

  templates/foreign目錄下的create_user.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/create_user/" method="post">
        <p>用戶名:{{ obj.username }}</p> {#<p>用戶組:{{ obj.user_group }}</p>#} <p>用戶組:{{ obj.user_group_id }}</p>
        <input type="submit" value="submit"/>
    </form>

    <table> {% for item in user_list %} <tr>
            <td>{{ item.username }}</td>
{#注意此處的操做,user_group是1個對象(表示數據庫中一行數據),而用戶組在數據庫中是按ID存儲的,因此要轉換成中文,注意模板中的.號操做#}
<td>{{ item.user_group.caption }}</td> </tr> {% endfor %} </table> </body> </html>

運行效果以下圖所示:

 實例2:在頁面查詢用戶,同時在頁面展現該用戶的相關信息

 在實例1的基礎上,修改views模塊中foreign.py文件便可

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django.shortcuts import HttpResponse,render from app01 import models from app01.forms import foreign as ForeignForm # 建立用戶組表
def create_user_group(request): # 建立用戶組的類型,運行一次後註釋,防止屢次生成
    # models.UserGroup.objects.create(caption='CEO')
    # models.UserGroup.objects.create(caption='CTO')
    # models.UserGroup.objects.create(caption='COO')
    return HttpResponse('ok') # 建立用戶表
def create_user(request): # 將請求數據做爲參數傳遞給UserForm,生成相應對象
    obj = ForeignForm.UserForm(request.POST) # 判斷請求類型是否爲'POST'類型
    if request.method == 'POST': # 進行From表單驗證,驗證其有效性
        if obj.is_valid(): # 獲取請求數據
            all_data = obj.clean() # 把獲取的數據存儲到數據庫,有3種方法
            # 第1種方法(對象級別操做):先獲取對象
            # group_obj = models.UserGroup.objects.get(id=all_data['group'])
            # 爲何建立數據庫表時,第二個參數(關聯外鍵)user_group=group_obj?
            # 這是由於在Model裏user_group = models.ForeignKey('UserGroup'),這裏user_group其實是關聯了一個對象,
            # 因此在傳遞參數時要傳遞相應的對象參數。
            # models.User.objects.create(username=all_data['username'],user_group=group_obj)

            # 第2種方法(數據庫級別操做,這裏注意Django默認給外鍵字段名加上了"_id")
            # models.User.objects.create(username=all_data['username'],user_group_id=all_data['group'])
            
            # 第3種方法(傳字典參數,可是要注意form中已經組成了字典數據)
            models.User.objects.create(**all_data) # 打印數據庫中因此信息的條數
            print models.User.objects.all().count() else: # 寫上報錯提示信息,form表單的驗證信息,這裏省略了
            pass
            
    # 根據輸入的用戶名,查找該用戶所在的組
    # 例如URL中輸入http://127.0.0.1:8000/create_user/?user=alex,表示獲取數據庫中username='alex'的相關數據
    # 獲取get請求中user的值,例如user='alex',那麼下面的val='alex'
    val = request.GET.get('user') # 獲取數據庫中對應字段username='val'的一行數據
    user_list = models.User.objects.filter(username=val) return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})

 運行效果以下圖所示:

實例3:在頁面查詢用戶組,同時在頁面展現該用戶組的用戶

在實例1的基礎上,修改views模塊中foreign.py文件便可

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django.shortcuts import HttpResponse,render from app01 import models from app01.forms import foreign as ForeignForm # 建立用戶組表
def create_user_group(request): # 建立用戶組的類型,運行一次後註釋,防止屢次生成
    # models.UserGroup.objects.create(caption='CEO')
    # models.UserGroup.objects.create(caption='CTO')
    # models.UserGroup.objects.create(caption='COO')
    return HttpResponse('ok') # 建立用戶表
def create_user(request): # 將請求數據做爲參數傳遞給UserForm,生成相應對象
    obj = ForeignForm.UserForm(request.POST) # 判斷請求類型是否爲'POST'類型
    if request.method == 'POST': # 進行From表單驗證,驗證其有效性
        if obj.is_valid(): # 獲取請求數據
            all_data = obj.clean() # 把獲取的數據存儲到數據庫,有3種方法
            # 第1種方法(對象級別操做):先獲取對象
            # group_obj = models.UserGroup.objects.get(id=all_data['group'])
            # 爲何建立數據庫表時,第二個參數(關聯外鍵)user_group=group_obj?
            # 這是由於在Model裏user_group = models.ForeignKey('UserGroup'),這裏user_group其實是關聯了一個對象,
            # 因此在傳遞參數時要傳遞相應的對象參數。
            # models.User.objects.create(username=all_data['username'],user_group=group_obj)

            # 第2種方法(數據庫級別操做,這裏注意Django默認給外鍵字段名加上了"_id")
            # models.User.objects.create(username=all_data['username'],user_group_id=all_data['group'])
            
            # 第3種方法(傳字典參數,可是要注意form中已經組成了字典數據)
            models.User.objects.create(**all_data) # 打印數據庫中因此信息的條數
            print models.User.objects.all().count() else: # 寫上報錯提示信息,form表單的驗證信息,這裏省略了
            pass
            
    # 根據輸入的用戶組,查找該組的全部用戶信息
    # http://127.0.0.1:8000/create_user/?usergroup=CEO
    # 獲取輸入的用戶組信息 
    val = request.GET.get('usergroup') # 跨表查詢,雙下劃線
    user_list = models.User.objects.filter(user_group__caption=val) return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})

 運行效果以下圖所示:

實例4:一對多連表關係中的多級關聯

  models.py文件

#/usr/bin/env python #-*- coding:utf-8 -*-

from __future__ import unicode_literals from django.db import models # Create your models here. #一對多連表關係中的多級關聯 #用戶類型表
class UserType(models.Model): type_list = models.CharField(max_length=64,null=True,blank=True) def __unicode__(self): return self.type_list # 用戶組表
class UserGroup(models.Model): caption = models.CharField(max_length=32) user_type = models.ForeignKey('UserType') def __unicode__(self): return self.caption # 用戶表
class User(models.Model): username = models.CharField(max_length=32) user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.username

   views模塊中foreign.py文件

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django.shortcuts import HttpResponse,render from app01 import models from app01.forms import foreign as ForeignForm #!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django.shortcuts import HttpResponse,render from app01 import models from app01.forms import foreign as ForeignForm def create_user_group(request): #添加用戶類型
    models.UserType.objects.create(type_list='金牌會員') models.UserType.objects.create(type_list='銀牌會員') models.UserType.objects.create(type_list='普通會員') #添加用戶組
    models.UserGroup.objects.create(caption='CEO',user_type_id=1) models.UserGroup.objects.create(caption='CTO',user_type_id=2) models.UserGroup.objects.create(caption='COO',user_type_id=3) return HttpResponse('OK') def create_user(request): obj = ForeignForm.UserForm(request.POST) if request.method == 'POST': if obj.is_valid(): all_data = obj.clean() #先獲取對象,而後把對象做爲參數
            group_obj = models.UserGroup.objects.get(id=all_data['user_group']) models.User.objects.create(username=all_data['username'],user_group=group_obj) # 測試1:獲取全部的用戶信息表
    # user_list = models.User.objects.all()

    #測試2:從URL中獲取請求的信息
    val = request.GET.get('usertype') # 注意跨表多級查詢外鍵時,雙下劃線的使用
    user_list = models.User.objects.filter(user_group__user_type__type_list=val) return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})

  forms模塊中foreign.py文件

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

from django import forms from app01 import models class UserForm(forms.Form): username = forms.CharField() user_group = forms.IntegerField(widget=forms.Select()) user_type = forms.IntegerField(widget=forms.Select()) def __init__(self,*args,**kwargs): super(UserForm,self).__init__(*args,**kwargs) self.fields['user_group'].widget.choices = models.UserGroup.objects.all().values_list('id','caption') self.fields['user_type'].widget.choices = models.UserType.objects.all().values_list('id','type_list')

  templates/foreign目錄下的create_user.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/create_user/" method="post">
        <p>用戶名:{{ obj.username }}</p>
        <p>用戶組:{{ obj.user_group }}</p>
        <p>用戶類型{{ obj.user_type }}</p>
        <input type="submit" value="submit"/>
    </form>

    <table> {% for item in user_list %} <tr>
            <td>{{ item.username }}</td>
            <td>{{ item.user_group.caption }}</td>
            <td>{{ item.user_group.user_type.type_list }}</td>
        </tr> {% endfor %} </table>
</body>
</html>

  測試1和測試2運行結果分別以下圖所示:(在實例4的多級關聯中,實際上用戶組合用戶類型是已經綁定死了的,不能選擇,例如加入用戶組是CEO,那麼用戶類型就是金牌會員,不能選擇)

                                                          

一對多小結:
一、外鍵user_group在數據庫中是以新字段名稱user_group_id(Django自動生成的名稱:外鍵名+'_id')存儲的,
   這樣將前端的數據存入數據庫時,就能夠構造字典參數,直接把字典做爲參數傳給數據庫建立函數create;
二、在實例中,外鍵user_group爲對象,對應着UserGroup中的一行數據;
三、數據庫中獲取數據採用"."操做符;
四、數據庫中跨表查詢關聯外鍵的字段值採用"__"雙下劃線操做符(注意雙下劃線操做符),好比實例中的
   user_list = models.User.objects.filter(user_group__caption=val),它表示查詢關聯外鍵user_group
   中caption字段值爲val的User表中的相關用戶數據

五、在外鍵的多級關聯中,在數據庫中查詢數據時,下劃線能夠連着使用

 

 參考資料:

      http://www.cnblogs.com/wupeiqi/articles/5246483.html

      http://www.cnblogs.com/luotianshuai/p/5301343.html              

相關文章
相關標籤/搜索