【发布时间】:2011-06-16 06:35:48
【问题描述】:
一定有办法通过 ORM 进行此查询,但我没有看到。
设置
我的模型如下:一个租户可以占用多个房间,一个用户可以拥有多个房间。因此,Rooms 对租户有一个 FK,对用户有一个 FK。房间也由(可能不同的)用户维护。
也就是说,我有这些(简化的)模型:
class Tenant(models.Model):
name = models.CharField(max_length=100)
class Room(models.Model):
owner = models.ForeignKey(User)
maintainer = models.ForeignKey(User)
tenant = models.ForeignKey(Tenant)
问题
给定一个租户,我希望用户拥有一个他们占用的房间。
相关的 SQL 查询是:
SELECT auth_user.id, ...
FROM tenants_tenant, tenants_room, auth_user
WHERE tenants_tenant.id = tenants_room.tenant_id
AND tenants_room.owner_id = auth_user.id;
例如,可以使用my_tenant.rooms.values_list('owner__email', flat=True) 从相关的用户对象中获取任何单独的值,但是获取完整的用户查询集让我很头疼。
通常一种解决方法是在我的Tenant 模型上设置一个ManyToMany 字段,指向User,TenantRoom 作为“直通”模型。但是,在这种情况下这不起作用,因为TenantRoom 模型有第二个(不相关的)ForeignKey 到User(see "restictions")。此外,租户模型似乎是不必要的混乱。
执行my_tenant.rooms.values_list('user', flat=True) 让我很接近,但返回用户 ID 的 ValuesListQuerySet 而不是实际用户对象的查询集。
问题
那么:有没有办法通过 ORM 仅使用一个查询来获取实际模型实例的查询集?
编辑
事实上,如果没有办法通过 ORM 直接在一个查询中执行此操作,那么完成我正在做的事情的最佳方式是什么(最高效、最惯用、最易读等的某种组合)寻找?以下是我看到的选项:
-
子选择
users = User.objects.filter(id__in=my_tenant.rooms.values_list('user')) -
通过 Python 进行子选择(请参阅 Performance considerations 了解其背后的原因)
user_ids = id__in=my_tenant.rooms.values_list('user') users = User.objects.filter(id__in=list(user_ids)) -
原始 SQL:
User.objects.all("""SELECT auth_user.* FROM tenants_tenant, tenants_room, auth_user WHERE tenants_tenant.id = tenants_room.tenant_id AND tenants_room.owner_id = auth_user.id""") 其他...?
【问题讨论】:
标签: python django django-models django-queryset django-orm