以相亲关系表举例,男女生信息表都放在一个数据表中,男生可以看到相亲过的女生,同理女生也可以看到相亲过的男生
1.前戏:通过外键表引出:
- 所有的信息都整合在一张表里,通过另一张按照自定义规则设置的外键表,实现连表操作查询的功能。
建立外键表:
- 由于是对同一张表操作,django框架此时就没有那么智能,此时就需要我们自定义约束规则,以规范使用!
PS:补充一点内容:ForeignKey()中的参数:
- to="表名"
- to_field="列名" #建立外键关系的列名,默认是id列
- related_query_name="自定义名" #定义一个反向操作的名称,保留了反向连表操作中_set的属性
- related_name="自定义名" #定义一个反向操作的名称,直接通过自定义名即可反向操作
related_query_name和related_name都是定义的反向操作的属性,一般常用于related_name.
举例说明:-外键表中,反向操作的名字,女生为a,男生为b!
# related_query_name
obj对象男.b_set.all()
obj对象女.a_set.all()
# related_name
obj对象男.a.all()
obj对象女.b.all()
1)models.py文件中,ORM利用类创建表的代码:
#创建用户信息表
class Userinfo(models.Model):
nickname = models.CharField(max_length=32) #昵称
username = models.CharField(max_length=32) #用户名
password = models.CharField(max_length=64) #密码
gender_choices = (
(1,"男"),
(2,"女"),
)
gender = models.IntegerField(choices=gender_choices) #性别
#外键关联表
class U2U(models.Model):
g = models.ForeignKey("Userinfo",related_name="boys") #设置与女生关联的外键,及反向操作的名称
b = models.ForeignKey("Userinfo",related_name="girls")#设置与男生关联的外键,及反向操作的名称
2)给两张表添加数据:
- 信息表就不用多说了,就是平常添加的顺序,此除多说说关联表,关联表添加数据的方式有两种:
#第一种:知道ID直接添加:
models.U2U.objects.create(b_id=1,g_id=4)
#第二种:先从信息表中,获取相对应的对象,然后在关联表中直接添加这个对象,内部会做转换操作,拿取用户的id。
boy = models.Userinfo.objects.filter(gender=1,id=2).first()
gril = models.Userinfo.objects.filter(gender=2,id=5).first()
models.U2U.objects.create(b=boy,g=gril)
3)表和数据都有了,那就剩下操作了,怎么获取相对应的信息!
- 此处再次普及一下正反向操作的定义:
正反向操作是以外键为标志,从当前有外键的表,通过外键获取对应表的数据操作称为正向操作;反之,从数据表反向获取关联表的操作,称为反向操作。
注意一点:不管是正反向操作,获取的对象(数据)都是跨表之后的另一张表的对象(信息)!
root = models.Userinfo.objects.filter(id=1).first() #先获取一个信息表的对象
result = root.girls.all() #通过定义的反向关联的名字,反向查找与当前对象有关系的对象,注意:此处获取的是 U2U表的对象!
for u in result:
print(u.g.nickname) #通过拿到的对象,在通过外键关系,正向获取有关系对象的昵称。
2.正题:
- 既然上边的操作可以实现信息的整合,那么建立联系的外键是否也可以写在一张表里呢?答案是肯定的。这种创建关联的方式就叫做自关联。
本质:把所有的信息都在一张表上创建,虽然只有一张表,但是我们可以再想象着生成一张一模一样的表,这两个表之间通过外联建立关系。
虽然是叫做自关联,实质上还是两张表的操作!
- M2M自关联特性:(多对多)
#创建自关联的整合表
class Userinfo(models.Model):
nickname = models.CharField(max_length=32) #昵称
username = models.CharField(max_length=32) #用户名
password = models.CharField(max_length=64) #密码
gender_choices = (
(1,"男"),
(2,"女"),
)
gender = models.IntegerField(choices=gender_choices) #性别
m = models.ManyToManyField('Userinfo')
#ManyToManyField有一特性,就是会自动生成一张关系表,我们设置的这个自关联表中,会生成三列,id,from_userinfo_id,to_userinfo_id
自增id不用说,from_userinfo_id,to_userinfo_id,从列名上就能看出来,分别代表着userinfo表的不同id,一个是从哪儿来,一个是去哪里。
obj = models.Userinfo.objects.filter(id=1).first()
# from_userinfo_id #正向操作 sql语句
obj.m => select xx from xx where from_userinfo_id = 1
# to_userinfo_id #反向操作 sql语句
obj.userinfo_set => select xx from xx where to_userinfo_id = 1
- 关系表内自定义规则:记住定义了规则之后,一定要严格遵守!!!
定义:
# 前面列:男生ID
# 后面列:女生ID
应用:
# 男生对象
obj = models.UserInfo.objects.filter(id=1).first()
# 根据男生ID=1查找关联的所有的女神
obj.m.all()
# 女生
obj = models.UserInfo.objects.filter(id=4).first()
# 根据女生ID=4查找关联的所有的男生
obj.userinfo_set.all()