Django默认ORM(七):一对一(O2O)自关联操作

以相亲关系表举例,男女生信息表都放在一个数据表中,男生可以看到相亲过的女生,同理女生也可以看到相亲过的男生

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()

  

 

 

 

posted @ 2017-09-22 17:31  Adamanter  阅读(1416)  评论(0编辑  收藏  举报