博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django 多表联合查询
阅读量:5815 次
发布时间:2019-06-18

本文共 7316 字,大约阅读时间需要 24 分钟。

一对多的表查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class 
Project(models.Model):
    
name 
= 
models.CharField(u
'项目名称'
,max_length
=
32
,blank
=
True
)
    
id 
= 
models.CharField(u
'项目ID'
,max_length
=
32
,unique
=
True
,primary_key
=
True
,blank
=
True
)
    
create_date 
= 
models.DateTimeField(u
'创建时间'
, auto_now_add
=
True
)
    
update_date 
= 
models.DateTimeField(u
'更新时间'
, auto_now
=
True
)
    
def 
__unicode__(
self
):
        
return 
self
.name
         
class 
Uhost(models.Model):
    
name 
= 
models.CharField(u
'计算机名'
,max_length
=
32
,blank
=
False
)
    
id 
= 
models.CharField(u
'实例ID'
,max_length
=
32
,blank
=
False
,primary_key
=
True
)
    
ip 
= 
models.GenericIPAddressField(u
'IP地址'
,blank
=
True
,null
=
True
)
    
cpu 
= 
models.CharField(u
'CPU/核'
,max_length
=
32
,blank
=
True
,null
=
True
)
    
memory 
= 
models.CharField(U
'内存/G'
,max_length
=
32
,blank
=
True
)
    
state 
= 
models.CharField(u
'实例状态'
,max_length
=
32
,blank
=
True
)
    
expiretime 
= 
models.DateTimeField(u
'到期时间'
, max_length
=
50
, null
=
True
, blank
=
True
)
    
isexpire 
= 
models.CharField(u
'是否过期'
, max_length
=
20
, blank
=
True
)
    
autorenew 
= 
models.CharField(u
'自动续费'
, max_length
=
20
, blank
=
True
)
    
tag 
= 
models.CharField(u
'业务组'
,max_length
=
32
,blank
=
True
)
    
networkstate 
= 
models.CharField(u
'网络状态'
,max_length
=
32
,blank
=
True
)
    
type 
= 
models.CharField(u
'实例类型'
,max_length
=
32
,blank
=
True
)
    
osfamily 
= 
models.CharField(u
'系统类型'
,max_length
=
32
,blank
=
True
)
    
ostype 
= 
models.CharField(u
'操作系统'
, max_length
=
50
, blank
=
True
)
    
chargetype 
= 
models.CharField(u
'付费类型'
, max_length
=
50
, blank
=
True
)
    
datadisk 
= 
models.IntegerField(u
'数据盘/G'
, blank
=
True
)
    
price 
= 
models.DecimalField(u
'价格'
,max_digits
=
8
,decimal_places
=
2
,null
=
True
,blank
=
True
)
    
zone 
= 
models.ForeignKey(Zone,verbose_name
=
u
'可用区'
,db_constraint
=
False
,on_delete
=
models.DO_NOTHING,blank
=
True
)
    
project 
= 
models.ForeignKey(Project,verbose_name
=
u
'所属项目'
,db_constraint
=
False
,on_delete
=
models.DO_NOTHING,blank
=
True
)
    
create_date 
= 
models.DateTimeField(u
'创建时间'
, auto_now_add
=
True
)
    
update_date 
= 
models.DateTimeField(u
'更新时间'
, auto_now
=
True
)
    
def 
__unicode__(
self
):
        
return 
self
.name

我建了两张表,project和uhost。

其中uhost表的project字段是设置了ForeignKey。

先看下project表中的内容。

1
2
3
4
5
6
7
8
9
10
11
>>> Project.objects.
all
()
[<Project: 上海别样红信息技术有限公司>, <Project: 备案专用>, <Project: gitlab>, 
<Project: PublicTest>, <Project: SPMS>, <Project: 安全测试>, <Project: OTA>, 
<Project: 
99
数据同步中转,本项目与
99
内网打通,不允许添加任何机器>, <Project: Ops>,
 
<Project: iPms>]
 
>>> Project.objects.
all
().values(
'id'
)
[{
'id'
: u
'org-81'
}, {
'id'
: u
'org-aws3dj'
}, {
'id'
: u
'org-et55qg'
}, 
{
'id'
: u
'org-ghan2t'
}, {
'id'
: u
'org-ja1wvv'
}, {
'id'
: u
'org-kbxrx4'
}, 
{
'id'
: u
'org-pni2a2'
}, {
'id'
: u
'org-qf4d2n'
}, {
'id'
: u
'org-vzfixt'
}, 
{
'id'
: u
'org-wrg10n'
}]

表查询:

查询uhost表中name中包含OPS10的所有主机对象

1
2
3
4
5
6
7
8
>>> Uhost.objects.
filter
(name__contains
=
'OPS10'
)
[<Uhost: SRV
-
OPS10
-
CS05>, <Uhost: SRV
-
OPS10
-
SPPX01>, <Uhost: SRV
-
OPS10
-
MAIL01>, 
<Uhost: SRV
-
OPS10
-
PROXY02>, <Uhost: SRV
-
OPS10
-
PROXY01>, <Uhost: SRV
-
OPS10
-
HAP02>,
 
<Uhost: SRV
-
OPS10
-
HAP01>, <Uhost: SRV
-
OPS10
-
ANSIBLE02>, <Uhost: SRV
-
OPS10
-
NGX01>, 
 
<Uhost: SRV
-
OPS10
-
NGX02>, <Uhost: SRV
-
OPS10
-
PROXY05>, <Uhost: SRV
-
OPS10
-
ANSIBLE06>, 
 
<Uhost: SRV
-
OPS10
-
DEPLOY01>, <Uhost: SRV
-
OPS10
-
NGINX01>, <Uhost: SRV
-
OPS10
-
ES02>, 
 
<Uhost: SRV
-
OPS10
-
ES03>, <Uhost: SRV
-
OPS10
-
ES01>, <Uhost: SRV
-
OPS10
-
LOGSTASH01>, 
 
<Uhost: SRV
-
OPS10
-
PROXY04>, <Uhost: SRV
-
OPS10
-
PROXY03>, 
'...(remaining elements truncated)...'
]

正向查询:

若关系模型A包含与模型B关联的关联字段, 模型A的实例可以通过关联字段访问与其关联的模型B的实例:

Django提供了一种使用双下划线__的查询语法:

例如:

1
Uhost.objects.
filter
(project__id
=
'org-81'
)

查找uhost表中,所有project id为org-81’的的主机

1
2
3
4
5
6
7
>>> Uhost.objects.
filter
(project__id
=
'org-81'
)
[<Uhost: dbbackupsyncer2>, <Uhost: SRV
-
CPMS10
-
WEB16>, <Uhost: SRV
-
CPMS10
-
WEB15>, 
<Uhost: publicconsole>, <Uhost: SRV
-
CPMS10
-
WEB14>, <Uhost: dbbackupsyncer>,
<Uhost: 官网>, <Uhost: 
99exchangedb
>, <Uhost: dc1>, <Uhost: dc2>, <Uhost: publicweb>, 
<Uhost: SRV
-
CPMS10
-
WEB13>, <Uhost: SRV
-
OTA10
-
WS04>, <Uhost: SRV
-
OTA10
-
WS05>, 
<Uhost: SRV
-
OPS10
-
CS05>, <Uhost: SRV
-
OTA10
-
WS03>, <Uhost: SRV
-
OTA10
-
WEB04>, 
<Uhost: SRV
-
OTA10
-
WEB03>, <Uhost: 
99datasyncer
>, <Uhost: SRV
-
CPMS10
-
WEB31>, 
'...(remaining elements truncated)...'
]

查询uhost表中project id包含‘ghan’的主机信息

1
2
3
4
5
>>> Uhost.objects.
filter
(project__id__contains
=
'ghan'
)
[<Uhost: SRV
-
OPS10
-
ANSIBLE06>, <Uhost: SRV
-
OPS10
-
DEPLOY01>, \
<Uhost: SRV
-
OPS01
-
DEPLOY01>, <Uhost: SRV
-
OPS10
-
NGINX01>, \
<Uhost: SRV
-
OPS10
-
ES02>, <Uhost: SRV
-
OPS10
-
ES03>, <Uhost: SRV
-
OPS10
-
ES01>,\
<Uhost: SRV
-
OPS10
-
LOGSTASH01>]

反向查询:

被索引的关系模型可以访问所有参照它的模型的实例,如Entry.blog作为Blog的外键,默认情况下Blog.entry_set是包含所有参照Blog的Entry示例的查询集,可以使用查询集API取出相应的实例。

查询project name为Ops的所有主机对象

1
2
3
4
5
>>> Project.objects.get(name
=
'Ops'
).uhost_set.
all
()
[<Uhost: SRV
-
OPS10
-
ANSIBLE06>, <Uhost: SRV
-
OPS10
-
DEPLOY01>,
<Uhost: SRV
-
OPS01
-
DEPLOY01>, <Uhost: SRV
-
OPS10
-
NGINX01>, 
<Uhost: SRV
-
OPS10
-
ES02>, <Uhost: SRV
-
OPS10
-
ES03>, <Uhost: SRV
-
OPS10
-
ES01>, 
<Uhost: SRV
-
OPS10
-
LOGSTASH01>]

查询project name为Ops的所有主机对象的name属性

1
2
3
4
5
>>> Project.objects.get(name
=
'Ops'
).uhost_set.values(
'name'
)
[{
'name'
: u
'SRV-OPS10-ANSIBLE06'
}, {
'name'
: u
'SRV-OPS10-DEPLOY01'
}, \
{
'name'
: u
'SRV-OPS01-DEPLOY01'
}, {
'name'
: u
'SRV-OPS10-NGINX01'
}, \
{
'name'
: u
'SRV-OPS10-ES02'
}, {
'name'
: u
'SRV-OPS10-ES03'
}, \
{
'name'
: u
'SRV-OPS10-ES01'
}, {
'name'
: u
'SRV-OPS10-LOGSTASH01'
}]

查询project name为Ops的,并且name包含OPS字符串的所有主机

1
2
3
4
5
>>> Project.objects.get(name
=
'Ops'
).uhost_set.
filter
(name__contains
=
'OPS'
)
[<Uhost: SRV
-
OPS10
-
ANSIBLE06>, <Uhost: SRV
-
OPS10
-
DEPLOY01>, 
<Uhost: SRV
-
OPS01
-
DEPLOY01>, <Uhost: SRV
-
OPS10
-
NGINX01>, 
<Uhost: SRV
-
OPS10
-
ES02>, <Uhost: SRV
-
OPS10
-
ES03>, <Uhost: SRV
-
OPS10
-
ES01>, 
<Uhost: SRV
-
OPS10
-
LOGSTASH01>]

一对多表创建对象:

1
2
3
4
>>> host
=
Uhost(
id
=
'aaaaa'
)
>>> host.project
=
Project.objects.get(
id
=
'org-81'
)
>>> host
=
Uhost(name
=
'SRV-TEST'
)
>>> host.save()

多对多的查询

示例:

1
2
3
4
5
6
7
8
9
10
11
12
class 
GroupInfo(models.Model):
    
name 
= 
models.CharField(U
'组名'
,max_length
=
32
,blank
=
True
)
    
def 
__unicode__(
self
):
        
return 
self
.name
         
         
class 
UserInfo(models.Model):
    
name 
= 
models.CharField(u
'姓名'
,max_length
=
32
,blank
=
True
)
    
email 
= 
models.EmailField(u
'邮箱'
)
    
group 
= 
models.ManyToManyField(GroupInfo)
    
def 
__unicode__(
self
):
        
return 
self
.name

查询:

从userinfo表开始查

1
2
3
4
>>> UserInfo.objects.get(name
=
'zeng'
).group.
all
()
[<GroupInfo: 运维组>, <GroupInfo: 报警组>]
>>> UserInfo.objects.get(name
=
'zeng'
).group.
filter
(name
=
'运维组'
)
[<GroupInfo: 运维组>]

从groupinfo表开始查

1
2
3
4
>>> GroupInfo.objects.get(name
=
'CTO'
).userinfo_set.
all
()
[<UserInfo: zhang>]
>>> GroupInfo.objects.get(name
=
'CTO'
).userinfo_set.values(
'name'
,
'email'
)
[{
'name'
: u
'zhang'
'email'
: u
'zhang@qq.com'
}]

多对多表 创建对象

1
2
3
>>> u 
= 
UserInfo(name
=
'he'
,email
=
'he@qq.com'
)
>>> u.save()
>>> u.group.add(GroupInfo.objects.get(name
=
'运维组'
))

注意:

要添加新对象时,首先必须保证该对象在做ManyToMany的两张表中存在才行,比如上面的例子,我想创建一个叫he的用户,组为运维组。但是he这个用户不存在,所以先必须创建he这个对象,才能给他添加到运维组。

本文转自 曾哥最爱 51CTO博客,原文链接:http://blog.51cto.com/zengestudy/1906221,如需转载请自行联系原作者
你可能感兴趣的文章
在最初使用screen时,感觉最不舒服的就是它的闪屏。当移动到行首或者行尾时,再尝试移动屏幕就......
查看>>
Arduino初初教程4——信号输入
查看>>
Python 代码风格 和 PEP8
查看>>
nodejs npm express安装
查看>>
Directory PickerController
查看>>
Aspose免费公开课报名倒计时最后1周
查看>>
开源 java CMS - FreeCMS2.2 角色管理
查看>>
引用计数基本知识 & PHP 的内存泄露
查看>>
个性化设置 MySQL prompt 提示符
查看>>
System.setProperty想到的
查看>>
抽象类
查看>>
linux下IPTABLES配置详解
查看>>
C++ 指针—02 指针与引用的对比
查看>>
关于BETA、RC、ALPHA、Release、GA等版本号的意义
查看>>
SQL优化
查看>>
Tomcat热部署的实现原理
查看>>
Android ------ 美团的Lint代码检查实践
查看>>
Selenium-Webdriver系列Python版教程(5)————如何定位 frame
查看>>
不积跬步无以至千里
查看>>
python函数中的*args和**kwds
查看>>