|
ORM:Object Relational Mapping(關系對象映射)
我們提供的服務有:成都網站設計、做網站、微信公眾號開發(fā)、網站優(yōu)化、網站認證、循化ssl等。為上千余家企事業(yè)單位解決了網站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的循化網站制作公司
我們寫的類表示數(shù)據庫中的表
我們根據這個類創(chuàng)建的對象是數(shù)據庫表里的一行數(shù)據
obj.id obj.name.....就是數(shù)據庫一行數(shù)據中的一部分數(shù)據
我們在學習django中的orm的時候,我們可以把一對多,多對多,分為正向和反向查找兩種方式。
1
2
3
4
5
6
7
| class UserType(models.Model):
caption = models.CharField(max_length=32)
class UserInfo(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
user_type = models.ForeignKey('UserType')#外鍵
|
正向查找:ForeignKey在 UserInfo表中,如果從UserInfo表開始向其他的表進行查詢,這個就是正向操作,反之如果從UserType表去查詢其他的表這個就是反向操作。
馬上就要開始我們的orm查詢之旅?。。?
建表+配置url+views中寫相應的函數(shù)
models.py(在django中僅且只能在這里寫數(shù)據庫的相關類)
1
2
3
4
5
6
7
| class UserType(models.Model):
caption = models.CharField(max_length=32)
class UserInfo(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
user_type = models.ForeignKey('UserType')
|
這里我們使用sqlite3數(shù)據庫,在settings中使用默認設置就可以了
url.py中的配置
1
2
3
4
5
6
7
8
9
| from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user_type',views.user_type),
url(r'^user_info',views.user_info),
]
|
views.py先不進行任何操作,我們先保證正常訪問已經設置的url
1
2
3
4
5
6
7
| from django.shortcuts import render,HttpResponse
def user_type(req):
return HttpResponse("ok")
def user_info(req):
return HttpResponse("ok")
|
先在表中插入幾個數(shù)據用于測試:
usertype表
userinfo表數(shù)據插入:
所以我們在創(chuàng)建UserType數(shù)據的時候有兩種方法:第一種方法是直接根據這個字段進行添加數(shù)據!給user_type 加 '_id'
1
2
3
4
| def user_info(request):
dic = {'username':'mosson','age':18,'user_type_id':1}
models.UserInfo.objects.create(**dic)
return HttpResponse('OK')
|
或者通過對象添加
1
2
3
4
5
6
7
| #先獲取組的對象
usertype = models.UserType.objects.fiter(id=2)
#添加的時候直接添加對象就可以
models.UserInfo.objects.create(username='seven',age=18,user_type=usertype)
#寫成一行也行
models.UserInfo.objects.create(username='lile',age=18,user_type=models.UserType.objects.filter(id=1))
|
django的get方法是從數(shù)據庫的取得一個匹配的結果,返回一個對象,如果記錄不存在的話,它會報錯。
django的filter方法是從數(shù)據庫的取得匹配的結果,返回一個對象列表,如果記錄不存在的話,它會返回[]。
我們在設計表結構的時候什么時候使用一對多呢?
比如我們在建立用戶的時候有個菜單讓我們選擇用戶類型的時候,使用一對多?。?
正向查:ForeignKey在UserInfo表里,如果根據UserInfo這張表去查詢這兩張關聯(lián)的表的合起來的內容就是正向查
反向查:ForeignKey不在UserType里,如果根據UserType這張表去查詢這兩張關聯(lián)的表的合起來的內容就是反向查
在django中外鍵就相當于簡單的使用__連表,在外鍵那個對象中封裝了user_type表中的所有字段
我們要查詢所有用戶為CEO的用戶,我們是不是的根據UserType這張表去查,如果是跨表查詢使用“雙下劃線” + 屬性
1
2
3
4
5
6
7
| from app01 import models
def index(req):
ret = models.UserInfo.objects.filter(user_type__caption='COO')
print(ret)
for item in ret:
print(item,item.username,item.age,item.user_type.caption)
return HttpResponse("OK")
|
查詢結果:
我們可以根據下面的命令,取出一個用戶組,那么對于這個用戶組他有多少個用戶呢?
1
| models.UserType.objects.get(id=1)
|
1
2
3
4
5
6
7
8
9
10
11
| obj=models.UserType.objects.get(id=1)
obj.caption====得到在UserType表中id為1對應的caption
obj.id======得到在UserType表中id為1
obj.userinfo_set #理解為一種能力,可以獲取所有當前這個用戶類型的用戶/或者這個用戶類型的多個用戶
obj.userinfo_set.all() #獲取所有用戶類型為COO的用戶
obj.userinfo_set.filter(username='tim') #獲取用戶類型為COO的并且用戶為tim的用戶
'''
這.userinfo_set.相當于什么?它相當于 models.UserInfo.objects.filter(user_type=obj)
'''
|
反向查詢實例:查詢COO用戶下的所有的用戶名
1
2
3
| ret = models.UserType.objects.filter(caption='COO').values('userinfo__username')
for item in ret:
print(item,type(item))
|
方法二、
1
2
3
4
| ret = models.UserType.objects.filter(caption='COO').first()
for item in ret.userinfo_set.all():
print(item.username)
|
總結:
正向查找:
filter(跨表的時候,應該是對象__跨表的字段)
獲取這個值的時候,拿到了一行數(shù)據的時候 line.對象.跨表的字段
反向查找:
filter(關聯(lián)這個表的表明) 自動創(chuàng)建和表明相同的對象,通過這個對象__跨表的字段
line.自動創(chuàng)建和表明相同的對象_set.方法
多對多和一對多沒有任何關系
models.py
1
2
3
4
5
6
7
8
| 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')
|
當我們在host表里和hostadmin表里添加數(shù)據時和第三章關系表沒有任何關系,當我們這樣去建立表時,第三張表里面的列就已經固定了,分別是這兩個表的id
給主機表添加數(shù)據:
1
2
3
4
5
6
7
8
9
10
11
| def index(req):
#主機數(shù)據
models.Host.objects.create(hostname='host1.test.com', port=80)
models.Host.objects.create(hostname='host2.test.com', port=80)
models.Host.objects.create(hostname='host3.test.com', port=80)
models.Host.objects.create(hostname='host4.test.com', port=80)
#用戶數(shù)據
models.HostAdmin.objects.create(username='alex', email='alex@qq.com')
models.HostAdmin.objects.create(username='mosson', email='mosson@qq.com')
models.HostAdmin.objects.create(username='aliven', email='aliven@qq.com')
models.HostAdmin.objects.create(username='wusir', email='wusir@qq.com')
|
數(shù)據中的效果:
空的關系表
多對多正向、反向添加數(shù)據
正向添加數(shù)據:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| def index(request):
#正向添加數(shù)據
#找到用戶dali這個
admin_obj = models.HostAdmin.objects.get(username='dali')
#找到主機
host_list = models.Host.objects.filter(id__lt=3)
#通過找到的dali的對象.add去添加數(shù)據
admin_obj.host.add(*host_list)
'''
admin_obj 通過大力這個對象.add 去操作的主機,
大力的ID為 2 主機ID為:(1,2)
那就會生成這樣的表:
#2 1
#2 2
'''
return HttpResponse('OK')
|
反向添加數(shù)據:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def index(request):
#反向添加數(shù)據
#獲取主機
host_obj = models.Host.objects.get(id=3)
#獲取用戶列表
admin_list = models.HostAdmin.objects.filter(id__gt=1)
#和一對多一樣的道理
host_obj.hostadmin_set.add(*admin_list)
#host_obj = 3 管理員ID = 2 3 4
#3 2
#3 3
#3 4
return HttpResponse('OK')
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| class HostInfo(models.Model):
hostname = models.CharField(max_length=32)
port = models.IntegerField()
class UserMap(models.Model):
username = models.CharField(max_length=32)
email = models.CharField(max_length=32)
#through告訴Django用那張表做關聯(lián)
host = models.ManyToManyField(HostInfo , through='HostRelation')
class HostRelation(models.Model):
host = models.ForeignKey('HostInfo')
user = models.ForeignKey('UserMap')
'''
并且這里我們可以添加多個關系,比如在加一個字段
usertype = models.ForeignKey('UserType')
或者增加一個普通字段
status = models.CharField(max_length=32)
'''
|
現(xiàn)在咱們自己創(chuàng)建了第三張表了?,F(xiàn)在我們已經會了兩種方式創(chuàng)建第三張表了,當我們使用自定義創(chuàng)建的第三張表的時候,在去添加數(shù)據的時候!
就不能使用第一種方式對象添加了!
現(xiàn)在我們有第三張表了這個對象了,我們就不需要管另外兩張表了,直接添加就行了! 0 0 !
添加主機和用戶--
1
2
3
4
5
6
7
8
9
10
11
| def index(req):
models.HostInfo.objects.create(hostname='alex.test.com', port=80)
models.HostInfo.objects.create(hostname='seven.test.com', port=80)
models.HostInfo.objects.create(hostname='mosson.test.com', port=80)
models.UserMap.objects.create(username='alex', email='alex@qq.com')
models.UserMap.objects.create(username='seven', email='seven@qq.com')
models.UserMap.objects.create(username='mosson', email='mosson@qq.com')
return HttpResponse('ok')
|
將數(shù)據插入到第三張表中---辦法1:
插入單條數(shù)據
1
2
3
4
5
6
| def index(request):
models.HostRelation.objects.create(
user = models.UserMap.objects.get(id=1),
host = models.HostInfo.objects.get(id=1)
)
return HttpResponse('OK')
|
多對多兩種方式對比和查詢
查詢--方法一:
第一種方式都是基于表中的對象去找到第三張表! 通過間接的方式找到這張表的句柄!
1
2
3
4
5
6
| #正向查
admin_obj = models.HostAdmin.objects.get(id=1)
admin_obj.host.all()
#反相差
host_obj = models.Host.objects.get(id=1)
host_obj.hostadmin_set.all()
|
查詢--方法二:
用第二種方法就沒有正向和反向這么一說了,直接查即可!
1
2
3
4
| relation_list = models.HostRelation.objects.all()
for item in relation_list: #每一個item就是一個關系
print (item.user.username)
print( item.host.hostname)
|
1
2
3
4
| relation_list = models.HostRelation.objects.filter(user__username='mosson')
for item in relation_list: #每一個item就是一個關系
print( item.user.username)
print (item.host.hostname)
|
通過第二種方式可以把所有的關系都找到,第一種方式可以把所有的關系表都找到嗎?
第一種方式只能找到某一個人管理的機器,不能把有的對應關系找到!
1
2
3
4
5
6
7
| class UserType(models.Model):
caption = models.CharField(max_length=32)
class UserInfo(models.Model):
user_type = models.ForeignKey('UserType') #這個user_type是一個對象,對象里面封裝了ID和caption
username = models.CharField(max_length=32)
age = models.IntegerField()
|
select_related的作用,他就是用來優(yōu)化查詢的,沒有他也可以,用它主要是用來優(yōu)化ForeignKey
1
2
3
4
5
6
7
| def index(request):
ret = models.UserInfo.objects.all()
#咱們看下他執(zhí)行的什么SQL語句
print( ret.query)
'''
SELECT "app01_userinfo"."id", "app01_userinfo"."user_type_id", "app01_userinfo"."username", "app01_userinfo"."age" FROM "app01_userinfo"
'''
|
加上select_related是什么樣子的