【问题标题】:Django queryset for intersecting ManyToMany relations fields用于交叉多对多关系字段的 Django 查询集
【发布时间】:2020-05-11 07:52:04
【问题描述】:

我有一个难题,我正在尝试选择具有多对多关系的相互关联的模型,具体取决于每个多对多字段上存在的模型的交集。我试图用 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)

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

  • 排除用户同时在事件的users字段、事件的want_private字段和users_a查询集中的事件。
  • 包括用户同时在事件的users字段中的事件,not在事件的want_private字段和@987654329 @查询集。

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

非常感谢,

卡米尔。

【问题讨论】:

  • 您能否澄清User.eventsEvent.want_private 的关系。对于您要存储的数据,用户是否有可能在Event.want_privateEvent.users
  • 嗨@solarissmoke,确实我应该提到这一点,不,User 不可能在want_private 中,但不在users 中。然而相反的情况是可能的,用户可以在users,但不能在want_private。谢谢!

标签: django database django-models orm


【解决方案1】:

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

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 本质上是用户与事件关联的附加标志,那么这个直通模型就是正确的数据结构。

【讨论】:

  • 非常感谢@solarissmoke,我没想到through,这是一个非常有趣的线索。我认为这在我的技能范围内。我会努力让它在我身边工作。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-21
  • 1970-01-01
相关资源
最近更新 更多