Django 第二个 m2m 关系

Django second m2m relation

我有两个模型:User 和 Board。

class Board(models.Model):
    title = models.CharField(max_length=20, verbose_name=u'Название')
    members = models.ManyToManyField(to='user.User', related_name='boards', verbose_name=u'Участники')

而且我想获得一份用户 ID 列表,这些用户 ID 至少与当前用户有一个公共板。如果我使用这个过滤器:

User.objects.filter(boards__members__id=self.request.user.id).values_list('id', flat=True)

它returns我

[1, 2, 6, 1, 2, 3]

我期待这个结果。但是当我使用:

self.request.user.boards.all().values_list('members__id', flat=True)

它returns给我一个列表,其中仅包含当前用户 ID。

[1, 1]

会发生什么?

UPD

我忘记了一件重要的事情:有一个函数,看起来像:

def has_related_value(obj, field, channel_val):
    filter_by_val = channel_val
    property_name, filter_by_val = field.split('__', 1)

    attr = getattr(obj, property_name)
    if hasattr(attr, 'all'):
        return getattr(obj, property_name).filter(**{filter_by_val: channel_val}).exists()

大致是这样称呼的:has_related_value(self.request.user, 'boards__members__id', self.request.user.id)。也许,我可以把return getattr(obj, property_name).filter(**{filter_by_val: channel_val}).exists()改成obj.__class__.objects.filter(pk=obj.pk, **{field: channel_val}).exists(),但我不想改变这个功能。所以,我尝试找到这样的 "field" 和 "channel_val" 值,这将是可行的。另外 "channel_val" 必须是常量,所以 "field" - "boards__in" 和 "channel_val" - self.connection.user.boards.all() 不起作用。

这是正确的行为,因为 self.request.user 指的是当前用户,这就是您获取当前用户关系对象的原因。如果你想要整个用户对象模型,你需要使用 Django 用户模型来获得结果

让我们稍微分解一下。首先,你想知道当前用户属于哪个版块:

boards = Board.objects.filter(members=self.request.user)

然后,您想知道属于这些版块的所有用户 ID(可能有重复,所以使用 distinct()):

User.objects.filter(
    boards__in=boards
).distinct().values_list('id', flat=True)

您可以将它们混合在一起:

User.objects.filter(
    boards__in=Board.objects.filter(members=self.request.user)
).distinct().values_list('id', flat=True)

现在,您唯一需要担心的是 request.user.id 可能在结果中。您可以使用 exclude 子句删除它:

User.objects.exclude(
    id=self.request.user.id
).filter(
    boards__in=Board.objects.filter(members=self.request.user)
).distinct().values_list('id', flat=True)