Django ManyToMany filter()

后端 未结 3 1331
星月不相逢
星月不相逢 2020-11-27 13:00

I have a model:

class Zone(models.Model):
    name = models.CharField(max_length=128)
    users = models.ManyToManyField(User, related_name=\'zones\', null=T         


        
相关标签:
3条回答
  • 2020-11-27 13:16

    Just restating what Tomasz said.

    There are many examples of FOO__in=... style filters in the many-to-many and many-to-one tests. Here is syntax for your specific problem:

    users_in_1zone = User.objects.filter(zones__id=<id1>)
    # same thing but using in
    users_in_1zone = User.objects.filter(zones__in=[<id1>])
    
    # filtering on a few zones, by id
    users_in_zones = User.objects.filter(zones__in=[<id1>, <id2>, <id3>])
    # and by zone object (object gets converted to pk under the covers)
    users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3])
    

    The double underscore (__) syntax is used all over the place when working with querysets.

    0 讨论(0)
  • 2020-11-27 13:21

    Note that if the user may be in multiple zones used in the query, you may probably want to add .distinct(). Otherwise you get one user multiple times:

    users_in_zones = User.objects.filter(zones__in=[zone1, zone2, zone3]).distinct()
    
    0 讨论(0)
  • 2020-11-27 13:21

    another way to do this is by going through the intermediate table. I'd express this within the Django ORM like this:

    UserZone = User.zones.through
    
    # for a single zone
    users_in_zone = User.objects.filter(
      id__in=UserZone.objects.filter(zone=zone1).values('user'))
    
    # for multiple zones
    users_in_zones = User.objects.filter(
      id__in=UserZone.objects.filter(zone__in=[zone1, zone2, zone3]).values('user'))
    

    it would be nice if it didn't need the .values('user') specified, but Django (version 3.0.7) seems to need it.

    the above code will end up generating SQL that looks something like:

    SELECT * FROM users WHERE id IN (SELECT user_id FROM userzones WHERE zone_id IN (1,2,3))
    

    which is nice because it doesn't have any intermediate joins that could cause duplicate users to be returned

    0 讨论(0)
提交回复
热议问题