简体   繁体   English

Django第二个M2M关系

[英]Django second m2m relation

I have two models: User and 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'Участники')

And I want to get a list of users ids, which have at least one common board with current user. 我想获得一个用户ID列表,该ID与当前用户至少有一个共同的董事会。 If I use this filter: 如果我使用此过滤器:

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

It returns me 它返回我

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

And I expect this result. 我期待这个结果。 But when I use: 但是当我使用时:

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

It returns me a list, which contains only current user id. 它返回一个列表,其中仅包含当前用户ID。

[1, 1] [1,1]

What happens? 怎么了?

UPD UPD

I forgot one important thing: there is a function, which look like: 我忘记了一件重要的事情:这里有一个函数,看起来像:

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()

And it is roughly called such: has_related_value(self.request.user, 'boards__members__id', self.request.user.id) . 大致称为: has_related_value(self.request.user, 'boards__members__id', self.request.user.id) Perhaps, I can change return getattr(obj, property_name).filter(**{filter_by_val: channel_val}).exists() to obj.__class__.objects.filter(pk=obj.pk, **{field: channel_val}).exists() , but i don't want to change this function. 也许,我可以将return getattr(obj, property_name).filter(**{filter_by_val: channel_val}).exists()更改为obj.__class__.objects.filter(pk=obj.pk, **{field: channel_val}).exists() ,但我不想更改此功能。 So, i try to find such "field" and "channel_val" values, that will be work. 因此,我尝试找到这样的“字段”和“ channel_val”值,这将是可行的。 Also "channel_val" must be constant, so "field" - "boards__in" and "channel_val" - self.connection.user.boards.all() does not work. 同样,“ channel_val”必须恒定,因此“ field”-“ boards__in”和“ channel_val”-self.connection.user.boards.all()不起作用。

It's the correct behavior because self.request.user refers to current user and that is why you are getting current user relationship objects. 这是正确的行为,因为self.request.user指向当前用户,这就是为什么要获取当前用户关系对象的原因。 If you want entire User object model you need to use Django User Model to get results 如果您想要整个User对象模型,则需要使用Django User Model来获取结果

Let's break this down a bit. 让我们分解一下。 First, you want to know what boards the current user belongs to: 首先,您想知道当前用户属于哪个委员会:

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

Then, you want to know all user ids that belong to those boards (there may be duplicates, so use distinct() ): 然后,您想知道所有属于这些板的用户ID(可能有重复的用户,所以请使用distinct() ):

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

You could mix those together: 您可以将它们混合在一起:

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

Now, the only thing you need to worry about is that request.user.id may be in the results. 现在,您唯一需要担心的是结果中可能存在request.user.id You could remove that using an exclude clause: 您可以使用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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM