django的自关联

自关联

表内自关联是指表内数据相关联的对象和表是相同字段,这样我们就直接用表内关联将外键关联设置成自身表的字段。同样表内关联也分一对多字段和多对多字段
例如:对于微博评论,每条评论都可能有子评论,但每条评的字段内容应该都是相同的,并且每条评论都只有一个父评论,这就满足了,一对多的情形。父评论为关联字段,可以对应多个子评论,这就是一对多的自关联。

一对多

在django项目的models中创建评论表。

#评论表
class Comment(models.Model):
    #评论的内容字段
    content=models.CharField(max_length=255)
    #评论的发布时间
    push_time=models.DateTimeField(auto_now_add=True)
    #关联父评论的id,可以为空
    pcomment = models.ForeignKey(to='self',null=True) 
    def __str__(self):
        return self.content

添加数据,第一条数据关联字段为空,说明是父评论,第二条数据关联了第一条数据说明是第一条数据的字评论,同样后两条数据是是第二条数据的子评论.

接下来查找第一条数据的子评论:

#第一条数据的id是1,可以通过筛选父评论关联字段等于1的对象
print(Comment.objects.filter(pcomment_id=1))

    #根据子评论关联id正向查找父评论的内容
    print(Comment.objects.filter(pcomment_id=2).values('pcomment__content'))



    #根据父评论的id反向查找子评论
    print(Comment.objects.filter(id=1).values('comment__id'))

注意:外键关联是在子评论中,有关联字段的是子评论,子评论查父评论是正向,父评论查子评论是反向。

多对多表自关联

建立一张表,表字段为姓名以及朋友多对多字段,一个人可有多个朋友,也可以是多个人的朋友,找一个人的朋友是正向查找,找是某个人的朋友是反向查找。

class Person(models.Model):
    name = models.CharField(max_length=12)
    #人和人交朋友
    friends = models.ManyToManyField(to='self',symmetrical=False,related_name='ship')
    def __str__(self):
        return self.name
   # 查找沁阳的基友
    #正向查找关联字段__name
    print(Person.objects.filter(name='沁阳').values('friends__name'))

    # 反向查找沁阳的基友
    # print(Person.objects.all().filter(ship__name='沁阳'))

    # 查找王帅的基友
    # 正向查找关联字段__name,王帅是沁阳的朋友但王帅的朋友是空,因为王帅没有关联别人
    print(Person.objects.get(name='王帅').friends.all())

    #反向查找是王帅朋友的人,也是空
    print(Person.objects.filter(ship__name='王帅'))


    # 基友是沁阳的那个人反向查找
    print(Person.objects.get(name='沁阳').ship.all())
    #基友是王帅的那个人反向查找
    # print(Person.objects.get(name='王帅').ship.all())

    # 基友含有沁阳的人反向
    print(Person.objects.filter(name='沁阳').values('ship__name'))

注意:查找某人的朋友是正向,查找朋友里面有某人的人是反向查找

反向名称related_name

反向名称,用来从被关联字段指向关联字段。

注意,在你定义 抽象 model (abstract models) 时,你必须显式指定反向名称; 只有在你这么做了之后, 某些特别语法 (some special syntax) 才能正常使用。

class Book(models.Model):
    name=models.CharField(max_length=20)
    pub=models.ForeignKey(Publisher,related_name='pub')
    authors=models.ManyToManyField(Author,related_name='author')

这样用Publisher或者Author反向查询Book时可以用related_name了:publisher1.pub.all()或者author1.author.all()。

如果不想设置反向关系,设置related_name为'+'或者以'+'结束。

user = models.ForeignKey(User, related_name='+')

如果有多个ManyToManyField指向同一个Model,这样反向查询FOO_set的时候就无法弄清是哪个ManyToManyField字段了,可以禁止反向关系:

users = models.ManyToManyField(User, related_name='u+')
referents = models.ManyToManyField(User, related_name='ref+')

参考资料
1
2

posted @ 2019-11-24 21:10  一起学编程  阅读(1544)  评论(0编辑  收藏  举报