Должен быть способ выполнить этот запрос через ORM, но я его не вижу.
Настройка
Вот то, что я моделирую: один Арендатор может занимать несколько комнат, а один Пользователь может иметь несколько комнат. Таким образом, номера имеют 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;
Получение любого отдельного значения из связанных объектов User может быть выполнено, например, с помощью my_tenant.rooms.values_list('owner__email', flat=True)
, но получение полного набора запросов пользователей приводит в замешательство.
Обычно одним из способов решения этой проблемы является установка поля ManyToMany
в моей модели Tenant
, указывающего на User
с TenantRoom
в качестве сквозной модели. Это не будет работать в этом случае, потому что модель TenantRoom
имеет вторую (не связанную) ForeignKey
до User
( см. «Ограничения» ). Плюс, это кажется ненужным беспорядком на модели Арендатора.
Выполнение my_tenant.rooms.values_list('user', flat=True)
приближает меня, но возвращает ValuesListQuerySet идентификаторов пользователей, а не набор запросов реальных объектов User.
Вопрос
Итак: есть ли способ получить набор запросов фактических экземпляров модели через ORM, используя только один запрос?
Редактировать
Если, на самом деле, нет способа сделать это непосредственно в одном запросе через ORM, то какой это лучший (некоторая комбинация наиболее производительного, наиболее идиоматического, наиболее читаемого и т. Д.) Способа выполнить то, что я находясь в поиске? Вот варианты, которые я вижу:
подвыбор
users = User.objects.filter(id__in=my_tenant.rooms.values_list('user'))
Подвыбрать через Python (см. Рекомендации по производительности для обоснования этого)
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""")
Другие ...