一對多:models.ForeignKey(其餘表) 應用場景: |
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)
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,那麼用戶類型就是金牌會員,不能選擇)
一對多小結: 五、在外鍵的多級關聯中,在數據庫中查詢數據時,下劃線能夠連着使用 |
參考資料:
http://www.cnblogs.com/wupeiqi/articles/5246483.html
http://www.cnblogs.com/luotianshuai/p/5301343.html