Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何按照双连接关系在Django中执行查询(或者:如何绕过Django对许多“通过”模型的限制?)_Python_Django_Django Models_Django Queryset_Django Orm - Fatal编程技术网

Python 如何按照双连接关系在Django中执行查询(或者:如何绕过Django对许多“通过”模型的限制?)

Python 如何按照双连接关系在Django中执行查询(或者:如何绕过Django对许多“通过”模型的限制?),python,django,django-models,django-queryset,django-orm,Python,Django,Django Models,Django Queryset,Django Orm,一定有办法通过ORM进行查询,但我没有看到 设置 以下是我正在建模的内容:一个租户可以占用多个房间,一个用户可以拥有多个房间。因此,房间有一个FK到租户和一个FK到用户。房间也由(可能不同的)用户维护 也就是说,我有这些(简化的)模型: 问题 给定一个租户,我希望用户拥有他们所居住的房间 相关的SQL查询将是: SELECT auth_user.id, ... FROM tenants_tenant, tenants_room, auth_user WHERE tenants_tenant.id

一定有办法通过ORM进行查询,但我没有看到

设置 以下是我正在建模的内容:一个租户可以占用多个房间,一个用户可以拥有多个房间。因此,房间有一个FK到租户和一个FK到用户。房间也由(可能不同的)用户维护

也就是说,我有这些(简化的)模型:

问题 给定一个租户,我希望用户拥有他们所居住的房间

相关的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\u tenant.rooms.values\u list('owner\u email',flat=True)
,但是获取完整的用户查询集让我很困惑

通常一种解决方法是在my
Tenant
模型上设置一个
ManyToMany
字段,指向
User
,将
TenantRoom
作为“直通”模型。但是,在这种情况下,这不起作用,因为
TenantRoom
模型有第二个(不相关的)
ForeignKey
User
()。此外,租户模型上似乎存在不必要的混乱

执行
my_tenant.rooms.values\u list('user',flat=True)
可以让我接近,但会返回用户ID的ValuesListQuerySet,而不是实际用户对象的queryset

问题 那么:有没有一种方法可以通过ORM只使用一个查询来获取实际模型实例的查询集


编辑

如果事实上,没有办法通过ORM在一个查询中直接实现这一点,那么实现我所寻找的目标的最佳方式是什么(最高效、最惯用、最可读等的组合)?以下是我看到的选项:

  • 再选择

    users = User.objects.filter(id__in=my_tenant.rooms.values_list('user'))
    
  • 通过Python进行子选择(请参阅以了解其背后的推理)

  • 原始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""")
    
  • 其他的


  • 正确的方法是使用
    related\u name

    class Tenant(models.Model):
        name = models.CharField(max_length=100)
    
    class Room(models.Model):
        owner = models.ForeignKey(User, related_name='owns')
        maintainer = models.ForeignKey(User, related_name='maintains')
        tenant = models.ForeignKey(Tenant)
    
    然后你可以这样做:

    jrb = User.objects.create(username='jrb')
    bill = User.objects.create(username='bill')
    bob = models.Tenant.objects.create(name="Bob")
    models.Room.objects.create(owner=jrb, maintainer=bill, tenant=bob)
    
    User.objects.filter(owns__tenant=bob)
    

    哇!放屁。我的模型上已经有相关的_名称,但为了尽量减少示例,我将它们作为(我认为是)无关的细节删除。我一心想弄清楚如何跟踪关系向前发展,不知何故,我错过了从用户后退的所有显而易见的解决方案。谢谢你帮我澄清@kRON我认为需要
    相关的\u名称
    ,因为房间模型上有两个FK供用户使用。默认情况下,Django将向用户模型添加一个
    room\u set
    属性,当存在一个FK时,该属性可以正常工作,但当添加第二个FK时,该属性会变得不明确(我怀疑发生的情况是,第二个FK只是破坏了第一个分配的
    room\u set
    ,但我尚未检查以确认)经过数小时对文档的仔细阅读,您的回答终于向我展示了相关的名称。非常感谢你,杰夫!
    class Tenant(models.Model):
        name = models.CharField(max_length=100)
    
    class Room(models.Model):
        owner = models.ForeignKey(User, related_name='owns')
        maintainer = models.ForeignKey(User, related_name='maintains')
        tenant = models.ForeignKey(Tenant)
    
    jrb = User.objects.create(username='jrb')
    bill = User.objects.create(username='bill')
    bob = models.Tenant.objects.create(name="Bob")
    models.Room.objects.create(owner=jrb, maintainer=bill, tenant=bob)
    
    User.objects.filter(owns__tenant=bob)