按自关系过滤对象

mrd*_*iri 1 django django-models

这是我的 Django 模型:

class Message(models.Model):
    text = models.TextField()
    parent = models.ForeignKey('Message', null=True, on_delete=models.SET_NULL)
    threads = ThreadManager()


class ThreadManager(models.Manager):
    def get_queryset(self):
        return super(ThreadManager, self).get_queryset().filter()
Run Code Online (Sandbox Code Playgroud)

如您所见,它使用自定义管理器。我ThreadManager想过滤具有自关系的消息。我的意思parent是指它的记录。( x.parent = x)

那要怎么写呢filter?有可能吗?

Wil*_*sem 5

自参考

您可以使用过滤器来寻址该pk列:

from django.db.models import F

Message.objects.filter(parent=F('pk'))
Run Code Online (Sandbox Code Playgroud)

所以这里我们指定 应该parent_id与主键相同,因此在这种情况下关系是循环的。

请注意,此过滤器不会检测长度大于 1 的循环。例如,如果我们有两条消息Aand B、andA.parent = BB.parent = A,则此过滤器将不会检测到这一点。它只检测Messages where A.parent == A

此外,Django 不执行语义检查:如果您稍后parent引用另一个模型,此过滤器不再有多大意义,但 Django 不会产生警告。

非自引用

如果我们想要相反,我们可以使用它.exclude(..)或将其包装到一个Q对象中:

# using exclude
Message.objects.exclude(parent=F('pk'))

# using Q
from django.db.models import Q

Message.objects.filter(~Q(parent=F('pk')))
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,Message要么没有父级,要么父级不是同一消息。