0. 对于ForeignKey的使用
0.1 概念
有ForeignKey的表成为子表,对应没有ForeignKey的表称为主表
0.2 方法
- 直接使用values或values_list得到数据
filter和values以及values_list中字段的使用按照以下规则
主表中使用自己的字段直接使用,如果使用子表字段按照子表小写表名__字段名称
子表中使用自己的字段直接使用,如果使用主表字段按照外键名__主表字段名称
的格式使用主表字段。
- 先获取对象再通过对象获取数据
filter中字段名的使用与上一条所述相同,区别在于使用first()或all()得到对象后通过对象得到数据的方法
主表对象查询子表
如果主表得到的对象为f,子表表名为Son,那么获取子表数据的方法有一下几种
f.son_set.all()
f.son_set.first()
f.son_set.values()
f.son_set.values_list()
子表对象查询主表
如果子表对象为s,子表中对应主表的外键为fk_father,那么可以使用s.fk_father
得到主表对象,通过主表对象可以得到主表中的各个数据。
1. 一对一
一对一有两种实现方式分别是ForeignKey+unique=True以及OneToOneField
使用ForeignKey的方式与上述ForeignKey的使用方一样,使用OneToOneField有别于ForeignKey的地方在于,通过主表对象查询子表时不需要使用_set
,可以直接使用子表名获取子表对象
举例说明w.blog_set.first().site
和w.blog.site
得到的结果是一样的,前者使用ForeignKey后者使用OneToOneField。
2. 一对多
通过外键建立一对多的关系
class UserGroup(models.Model):
title = models.CharField(max_length=32)
class UserInfo(models.Model):
user = models.CharField(max_length=32)
password = models.CharField(max_length=32)
age = models.IntegerField(default=0)
fk_ug = models.ForeignKey('UserGroup', null=True)
得到的表如下所示:
# UserGroup
id|title
1 |r&d
2 |sales
3 |financial
# UserInfo
id|user|age|fk_ug_id|password|
1 |Jack|18 |1 |123
2 |Mike|28 |2 |123
3 |Dick|34 |3 |123
4 |Kate|23 |1 |123
5 |Zake|25 |1 |123
2.1 子表查询主表
- 先获取子表对象再查询数据
filter中如果使用子表字段可以直接使用,如果使用主表字段获取子表对象,需要使用外键名__主表字段
的格式来获取子表对象
查询子表数据通过子表对象调用子表中的外键然后查询主表数据,查询格式子表对象.外键字段名.主表字段名
v = models.UserInfo.objects.filter(id=1).first()
print(v.user, v.password, v.age, v.fk_ug.title)
- 直接使用values跨表查询数据
在values中直接使用外键名实现跨表查询数据,查询格式外键字段名__主表字段名
ret = models.UserInfo.objects.all().values('id', 'user', 'fk_ug__title')
for item in ret:
print(item['id'], item['user'], item['fk_ug__title'])
"""
1 Jack r&d
2 Mike sales
3 Dick financial
4 Kate r&d
5 Zake r&d
"""
上面两种方法都可以实现跨表查询,但是第一种每查询一次都要操作一次数据库,二第二种只操作一次数据库,拿到所有数据。
2.2 主表查询子表
- 先获取主表对象再查询数据
filter中如果使用主表字段直接使用,如果使用子表字段获取主表对象需要使用子表表名__子表字段
的格式
通过主表对象查询子表数据,由于主表中没有外键需要使用_set
查询子表
obj = models.UserGroup.objects.filter(id=1).first()
print(obj.userinfo_set) # singleTable.UserInfo.None
print(obj.userinfo_set.all()) # <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
for row in obj.userinfo_set.all():
print(row.user, row.age)