首页 > 解决方案 > 用于交叉多对多关系字段的 Django 查询集

问题描述

我有一个难题,我试图选择具有多对多关系的相互关联的模型,具体取决于每个多对多字段上存在的模型的交集。我试图用 F() 来实现这一点,但没有成功,我认为我对 DB/ORM 的熟练程度不足以解决这个问题。

这是一个例子:

class Event(models.Model):
    want_private = models.ManyToManyField('User')

class User(AbstractUser):
    events = models.ManyToManyField(Event, related_name='users')

首先,我想从一组用户中选择事件,例如以“a”开头的那些:

users_a = User.objects.filter(username_startswith="a")

所以查询集应该是:

Event.objects.filter(users=users_a)

当事情变得复杂时,我想:

有没有人有办法解决这个问题?

非常感谢,

卡米尔。

标签: djangodatabasedjango-modelsorm

解决方案


根据您上面的评论,似乎用户可以与事件相关联,并且他们的关联是公开的或私有的(我正在解释want_private这里可能意味着什么)。如果是这种情况,那么我建议您更改数据结构,并将此信息存储在through 模型中。像这样的东西:

class Event(models.Model):
    # Remove want_private from here.

class User(AbstractUser):
    events = models.ManyToManyField(Event, related_name='users', through=UserEvent)

class UserEvent(models.Model):
    """ Through model between event and user. Store want_private here."""
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.CASCADE)
    want_private = models.BooleanField()  # This is now a boolean field

我在上面链接到的文档中解释了它是如何工作的。

现在,您的事件查询变得更加简单:

Event.objects.filter(users__username__startswith='a', userevent__wants_private=False)

这将为您提供至少一个用户与该事件相关联的所有事件,并且他们的关联不是私有的。如果某个事件的用户同时属于这两个类别,则此查询将包括该事件。

我在这里对 的含义做了一些假设want_private。如果want_private本质上是用户与事件关联的附加标志,那么这个贯穿模型就是正确的数据结构。


推荐阅读