如何使用distinct过滤ManyToManyField?

时间:2017-08-13 23:34:39

标签: python django django-models django-orm

我正在使用Django + postgres并拥有此模型:

class Room(models.Model):
    users = models.ManyToManyField(settings.AUTH_USER_MODEL)
    type = models.IntegerField(default=1)

room表数据示例:

____________________
| id      | type  |
|--------------------
| 1       | 1     |
| 2       | 1     |
| 3       | 2     |
 ...

room_users表数据示例:

____________________
| room_id | user_id |
|--------------------
| 1       | 100     |
| 1       | 101     |
| 2       | 100     |
| 2       | 102     |
| 3       | 103     |
 ...

:如何获得room_id 2个用户参与且房间有type=1?如您所知,ManyToManyField会自动创建room_users表。以下是我直接访问room_users的示例代码,但我不知道如何(room_users因为ManyToManyField而未在django中显示为模型:

user_id_1 = 100
user_id_2 = 101    
rooms = Room.objects.filter(users__in=[user_id_1, user_id_2], type=1).distinct("users__room_id").values_list("users__room_id", flat=True)
# result must me rooms[0].id = 1, len(rooms) = 1

对于这种情况,错误是:

django.core.exceptions.FieldError: Cannot resolve keyword 'room_id' into field. Choices are: date_joined, email, first_name, groups, id, is_active, is_staff, is_superuser, last_login, last_name, logentry, password, user_permissions, username

2 个答案:

答案 0 :(得分:1)

我不知道在考虑性能时,这是解决问题的最佳方法。

我的想法

user1 = User.objects.get(id=100).room_set.all()
user2 = User.objects.get(id=101).room_set.all()

same_room = user1.intersection(user2)

如果需要,请检查Django manual about intersection

答案 1 :(得分:0)

rooms = Room.objects.filter(type=1)
rooms = rooms.annotate(num_guests=Count('users')).filter(num_guests=2)

我添加了另一个类型1的房间进行测试,一个用户留在房间里 使用shell最终获得2,我更喜欢分两部分

To get the detail, iterate over the queryset