Django之model联表:一对多、跨表操作,联表查询
表结构概述
model.py :
class Something(models.Model):
name = models.CharField(max_length=32) class UserType(models.Model):
caption = models.CharField(max_length=32)
s = models.ForeignKey('Something')
#这个s不是字段名,字段名是something_id,这里的s作用是查询的时候用:row.s.id或row.s.name # 超级管理员,普通用户,游客,黑河
class UserInfo(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
user_type = models.ForeignKey('UserType')
# user_type_id
关系:
- something --> usertype 一对多
- usertype --> userinfo 一对多
表单中的数据:
something:
id | name |
---|---|
1 | something1 |
2 | something2 |
usertype:
id | caption | something_id |
---|---|---|
1 | 超级管理员 | 1 |
2 | 普通管理员 | 1 |
3 | 黑客 | 2 |
userinfo:
id | user | pwd | usertype_id |
---|---|---|---|
1 | alex | 123 | 1 |
2 | eric | 123 | 2 |
简要说明
Django中:
- 某表中foreignkey关联另一张表后,会自动在本表单中创建一个名称为另一张表的列:xxx_id
- 一对多创建时,foreignkey需要使用在一对多中的多的表单中
查询
userinfo_obj = UserInfo.objects.all()
结果为一个类的列表,类似:[UserInfo对象,UserInfo对象,]
以上语句会得到的数据为一个元素为查询目标表单对象
的列表,所以例子中的userinfo_obj为一个queryset对象我们可以通过`print(userinfo_obj.query)来查看SQL语句.
取值
比较简单:
id = userinfo_obj[0].user.id
user = userinfo_obj[0].user.user
pwd = userinfo_obj[0].user.pwd
...
values与vlue_list
queryset = UserInfo.objects.all().values('user')
结果:
[{‘user’: 'alex'},{‘user’: 'eirc'}] ================================= queryset = UserInfo.objects.all().value_list('user')
结果:
[('alex'),('eirc')]
查询中:
- 使用values('列名称'),结果为字典组成的列表
- 使用value_list('列名称'),结果为元组组成的列表
所以,未来操作中,我们可以使用这两个方便的东西来遍历字典取值还是使用元组取值
一对多操作
创建数据
一般我们是来这么做的:
UserInfo.objects.create(user='cc','pwd' = '123',user_type=UserType.objects.get(id=2))
很麻烦吧,其实是两步操作了,但因为建表时有了user_type_id,所以我们可以这么搞:
UserInfo.objects.create(user='cc','pwd'='123',user_type_id=2)
很简单吧...
数据查询
单表查询:
UserInfo.objects.filter(user='alex')
反向查询
需求:查询所有用户类型等于 普通用户 的所有用户名和密码
两步操作:
uid = UserType.objects.filter(caption='普通用户')
userinfo_obj = UserInfo.objects.filter(user_type_id=uid)
两步操作很简单,那就引出了神奇的双下划线:__
queryset = UserInfo.objcets.filter(user_type__caption='普通用户') ###结果
[UserInfo对象,UserInfo对象,UserInfo对象,]
row = queryset[0] #取到一个元素
user = row.user
password = row.pwd #取到具体信息
row.user_type.id
row.user_type.caption
总结下:
- 一对多中,正下查询使用foreignkey 的 _id 查询:row.外键字段.外键表的字段
- 一对多中反向查询,首先还是在在一对多中的多的表单中查询,可以使用
__
连接相关表中的列名去查询:row__
其实感觉__
有点像关系连线的意思
queryset = UserInfo.objects.filter(user_type__caption='普通用户').values('user','pwd','user_type__caption')
####结果 [{'user':'alex','pwd':'123','user_type__caption':'普通用户'}{'user':'eric','pwd':'123','user_type__caption':'普通用户'}]
三张表跨表操作
跟上面一样,直接用__
即可
queryset = UserInfo.objects.filter(user_type__s__name='xxx')
进阶操作
获取个数:
UserInfo.objects.filter(name = 'alex').count()
大于小于,还是使用双下划线__
UserInfo.objects.filter(id__gt=2)#获取ID大于2的数据
UserInfo.objects.filter(id__lt=5)#获取ID小余5的数据
UserInfo.objects.filter(id__gt=2,id__lt=5) #获取ID大于2小于5的数据
in:
UserInfo.objects.filter(id__in=[11,22,33]) #获取id等于11、22、33的数据
UserInfo.objects.exclude(id__in=[11,22,33]) #not in
contains(包含):
UserInfo.objects.filter(name__contains="ven") #获取name列中包含'ven'的数据
UserInfo.objects.filter(name__icontains="Ven") #获取name列中包含'ven'的数据,对大小写不敏感
UserInfo.objects.exclude(name__icontains="ven") #不包含
range:
UserInfo.objects.filter(id__range=[1,10]) #范围,between and ,获取id在1到10范围中的数据
联表查询
用原生代码联表:
from django.db import connection
cursor = connection.cursor()
sql = "select sum(d.count) from t_script_detail_desc as d left join t_scripts as s on d.script_id = s.script_id where d.create_time ='%s' and s.script_area = %s" %(one,self.area)
cursor.execute(sql)
num=cursor.fetchall()
有做外键关联的:
ShareScripts.objects.filter(share_obj__script_area=self.area,share_time__range=[starttime,stoptime]).count()
没有外键关联的联表,用extra:
#2个表关联
num=OperationTask.objects.filter(task_create_time__range=[starttime,stoptime],task_area=x).extra(select={'temp_type_id':'temp_type_id'},tables=['t_operation_templet'], where=['task_temp_id = temp_id']).values('temp_type_id').annotate(c=Count('task_id')).values('temp_type_id','c')
#3个表关联
result=OperationTask.objects.filter(task_create_time__range=[starttime,stoptime]).extra(select={'temp_type_id':'temp_type_id','name':'oper_type_name'},tables=['t_operation_templet','t_operation_types'], where=['task_temp_id = temp_id','temp_type_id = t_operation_types.id']).values('temp_type_id').annotate(c=Count('task_id')).values('name','c')
没有外键关联的联表,用extra 条件搜索:
num = ScriptsDetailDesc.objects.filter(create_time=one).extra(
tables=['t_scripts'],
where=['t_script_detail_desc.script_id = t_scripts.script_id','script_area =%s'],params = [self.area]).aggregate(Sum('count'))
num = ScriptsDetail.objects.filter(update_time__startswith=one).extra(
tables=['t_scripts'],
where=['t_script_detail.script_id = t_scripts.script_id','t_scripts.script_area =%s'],params = [self.area]).count()
部分参考:https://www.cnblogs.com/ccorz/p/5864470.html
Django之model联表:一对多、跨表操作,联表查询的更多相关文章
- Django中多表的增删改查操作及聚合查询、F、Q查询
一.创建表 创建四个表:书籍,出版社,作者,作者详细信息 四个表之间关系:书籍和作者多对多,作者和作者详细信息一对一,出版社和书籍一对多 创建一对一的关系:OneToOne("要绑定关系的表 ...
- 自定义类StyleSheet跨浏览器操作样式表中的规则
这是群里网友地瓜提供的一个类,不熟悉样式表对象和样式规则对象的浏览器差异的可以看看 /** * Stylesheet.js: utility methods for scripting CSS sty ...
- 【TP3.2】跨库操作和跨域操作
一.跨库操作:(同一服务器,不同的数据库) 假设UserModel对应的数据表在数据库user下面,而InfoModel对应的数据表在数据库info下面,那么我们只需要进行下面的设置即可. class ...
- SQL Server 跨服务器操作
Ø 简介 在工作中编写 SQL 时经常会遇到跨库或跨服务器操作,比如查询时,通过 A 服务器的某张表关联 B 服务器某张表,进行连接查询.或者从另一台服务器中的数据,对当前数据库中的数据进行 CRU ...
- How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置
原文:How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置 IS脚本操作注册表在64位平台下必须有特殊的设置 if (SYSINFO.bIsWow64) then ...
- MySQl的库操作、表操作和数据操作
一.库操作 1.1库的增删改查 (1)系统数据库: performance_schema:用来收集数据库服务器的性能参数,记录处理查询时发生的各种事件.锁等现象 mysql:授权库,主要存储系统用户的 ...
- Django之model补充:一对多、跨表操作
表结构概述 model.py : class Something(models.Model): name = models.CharField(max_length=32) class UserTyp ...
- django(3) 一对多跨表查询、ajax、多对多
1.一对多跨表查询获取数据的三种形式:对象.字典.元组 例:有host与business两张表,host与business的id字段关联,business在host表中的对象名是b, 通过查询hos ...
- 六、Django学习之基于下划线的跨表查询
六.Django学习之基于下划线的跨表查询 一对一 正向查询的例子为 已知用户名,查询用户的电话号码.反向查询例子反之. 正向查询 其中下划线前的表示表名,无下划线的表示的是Author表 resul ...
随机推荐
- 使用map()的小陷阱:parseInt
假设我们想要把一个字符串数组的每一项转换成整数,我们很自然就想到了把parseInt作为回调函数传给map()函数,但这样做可能会出现意想不到的结果: var strArr = ["1&qu ...
- 关于Ble通信库BluetoothKit的使用 以及可能出现的问题分析
首先,这个库是用于BLE(低功耗蓝牙)通信的,地址:https://github.com/dingjikerbo/BluetoothKit 当然,也可以选择根据andorid提供的底层接口自己完成这部 ...
- 牛客网PAT乙级(Basic Level)真题-数素数 (20)
题目描述 令Pi表示第i个素数.现任给两个正整数M <= N <= 10000,请输出PM到PN的所有素数. 输入描述: 输入在一行中给出M和N,其间以空格分隔. 输出描述: 输出从PM到 ...
- httpd does not appear to be running and proxying cobbler, or SELinux is in the way.
当我们执行cobbler check时,出现这种错误:httpd does not appear to be running and proxying cobbler, or SELinux is i ...
- CMake 构建项目教程-简介
CMake 构建项目教程-简介 Linux 平台构建项目,选择了CLion作为C++的IDE,而CLion默认就是使用CMake构建项目,所以这里记录了CMake在构建项目过程的一些小知识. 1. 项 ...
- Mac添加环境变量方法
一句话总结:找到paths文件编辑一下把要加路径写进去 转载注明出处http://www.cnblogs.com/billyrun/p/8631165.html 1.终端输入命令open /etc 开 ...
- 缓慢拒绝服务攻击- slowloris.pl
How use Slowloris Requirements: # sudo apt-get update # sudo apt-get install perl # sudo apt-get i ...
- zombodb 几点说明
内容来自官方文档,截取部分 默认es 索引的副本为0 这个参考可以通过修改索引,或者在创建的时候通过with 参数指定,或者通过pg 的配置文件中指定 索引更多的列以为这使用了更多的es 能力 索引的 ...
- Python(一)—— 控制流:if & for & while
基操 编程语言类 编译型 程序在执行之前需要一个专门的编译过程,把程序编译成 为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了.程序执行效率高,依赖编译器,跨平台性差些.缺点:编译之后 ...
- JS 点击复制
一.原理分析 浏览器提供了 copy 命令 ,可以复制选中的内容 document.execCommand("copy") 如果是输入框,可以通过 select() 方法,选中输入 ...