扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
|
ORM:Object Relational Mapping(关系对象映射)
我们提供的服务有:成都网站设计、做网站、微信公众号开发、网站优化、网站认证、循化ssl等。为上千余家企事业单位解决了网站和推广的问题。提供周到的售前咨询和贴心的售后服务,是有科学管理、有技术的循化网站制作公司
我们写的类表示数据库中的表
我们根据这个类创建的对象是数据库表里的一行数据
obj.id obj.name.....就是数据库一行数据中的一部分数据
我们在学习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中写相应的函数
models.py(在django中仅且只能在这里写数据库的相关类)
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数据库,在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")
|
先在表中插入几个数据用于测试:
usertype表
userinfo表数据插入:
所以我们在创建UserType数据的时候有两种方法:第一种方法是直接根据这个字段进行添加数据!给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方法是从数据库的取得一个匹配的结果,返回一个对象,如果记录不存在的话,它会报错。
django的filter方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在的话,它会返回[]。
我们在设计表结构的时候什么时候使用一对多呢?
比如我们在建立用户的时候有个菜单让我们选择用户类型的时候,使用一对多!!
正向查:ForeignKey在UserInfo表里,如果根据UserInfo这张表去查询这两张关联的表的合起来的内容就是正向查
反向查:ForeignKey不在UserType里,如果根据UserType这张表去查询这两张关联的表的合起来的内容就是反向查
在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(跨表的时候,应该是对象__跨表的字段)
获取这个值的时候,拿到了一行数据的时候 line.对象.跨表的字段
反向查找:
filter(关联这个表的表明) 自动创建和表明相同的对象,通过这个对象__跨表的字段
line.自动创建和表明相同的对象_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表里添加数据时和第三章关系表没有任何关系,当我们这样去建立表时,第三张表里面的列就已经固定了,分别是这两个表的id
给主机表添加数据:
1
2
3
4
5
6
7
8
9
10
11
| def index(req):
#主机数据
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)
#用户数据
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')
|
数据中的效果:
空的关系表
多对多正向、反向添加数据
正向添加数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| def index(request):
#正向添加数据
#找到用户dali这个
admin_obj = models.HostAdmin.objects.get(username='dali')
#找到主机
host_list = models.Host.objects.filter(id__lt=3)
#通过找到的dali的对象.add去添加数据
admin_obj.host.add(*host_list)
'''
admin_obj 通过大力这个对象.add 去操作的主机,
大力的ID为 2 主机ID为:(1,2)
那就会生成这样的表:
#2 1
#2 2
'''
return HttpResponse('OK')
|
反向添加数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def index(request):
#反向添加数据
#获取主机
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用那张表做关联
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)
'''
|
现在咱们自己创建了第三张表了。现在我们已经会了两种方式创建第三张表了,当我们使用自定义创建的第三张表的时候,在去添加数据的时候!
就不能使用第一种方式对象添加了!
现在我们有第三张表了这个对象了,我们就不需要管另外两张表了,直接添加就行了! 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')
|
将数据插入到第三张表中---办法1:
插入单条数据
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的作用,他就是用来优化查询的,没有他也可以,用它主要是用来优化ForeignKey
1
2
3
4
5
6
7
| def index(request):
ret = models.UserInfo.objects.all()
#咱们看下他执行的什么SQL语句
print( ret.query)
'''
SELECT "app01_userinfo"."id", "app01_userinfo"."user_type_id", "app01_userinfo"."username", "app01_userinfo"."age" FROM "app01_userinfo"
'''
|
加上select_related是什么样子的