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 ...
随机推荐
- 【未解决】对于使用Windows的IDEA进行编译的文件,但无法在Linux系统中统计代码行数的疑问
在我学习使用Windows的IDEA的过程中,将代码文件转移到Linux虚拟机当中,但无法在Linux系统中统计代码行数. 注意:拷贝进虚拟机的文件均能编译运行. 具体过程如下: root@yogil ...
- JPA问题汇总
JPATools生成的实体类对大小写敏感.如果一个数据库中大小写混乱,生成的实体类也会大小写都有.这种情况会导致HibernateSQL语句查询,每次都会查询第一个大小写字段,所以需要加映射关系.@C ...
- Linux 驱动——Led驱动1
led_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/init ...
- 微信小程序富文本中的图片大小超出屏幕
这个问题我在小程序社区中提的,后来有个帮我回答了这个问题,我试了一下可以. 解决办法是过滤富文本内容,给图片标签添加一个样式,限制图片的最大宽度. replace(/\<img/gi, '& ...
- python 写的员工信息查询
#!/use/bin/env pythonn#_*_ coding:utf-8 _*_import timedef Bre(): while True: Bre_falg = ra ...
- 【leetcode】438. Find All Anagrams in a String
problem 438. Find All Anagrams in a String solution1: class Solution { public: vector<int> fin ...
- Gym - 101201E:Enclosure (点到凸包的切线)
题意:给点N棵树,前K棵是已经拥有的,现在可以再拥有一棵树,问形成的最大凸包面积. 思路:先求K棵树的凸包C,然后对于后面的N-K棵树,我们先判断是否在凸包内,如果不在,我们要求两个切线. 这里分类讨 ...
- Codeforces1062C. Banh-mi(贪心+快速幂)
题目链接:传送门 题目: C. Banh-mi time limit per test second memory limit per test megabytes input standard in ...
- Python手记(二)
1.map函数 map函数用于将指定的数据成员都使用指定函数进行处理. 比如: map(float, arr) map(square, arr) 这两个函数分别将arr中成员转换为float类型,以及 ...
- Excel技巧--巧用差异化插入空行
假设有上面这一列,要求在不同城市之间插入一空行相隔开.数据少的时候可以手动操作,但数据量大时,就需要以下技巧: 1.复制该列(除去标题),并粘贴到右侧一列,但上方要隔开一个单元格B2: 2.将这两列选 ...