【问题标题】:Get a queryset of objects through an intermediary model通过中间模型获取对象的查询集
【发布时间】:2009-09-13 14:05:38
【问题描述】:

我想获取与某个 content_object 相关的所有 Geom 对象(请参阅我在底部尝试构建的函数 get_geoms_for_obj()

class Geom(models.Model):
    ...

class GeomRelation(models.Model):
    ''' For tagging many objects to a Geom object and vice-versa'''

    geom = models.ForeignKey(Geom)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

def get_geoms_for_object(obj):
    ''' takes an object and gets the geoms that are related

    '''
    ct = ContentType.objects.get_for_model(obj)
    id = obj.id
    grs = GeomRelation.objects.filter( content_type=ct, object_id=id )
    # how with django orm magic can I build the queryset instead of list
    # like below to get all of the Geom objects for a given content_object
    geoms = []
    for gr in grs:
        geoms.append(gr.geom)
    return set(geoms)
    # A set makes it so that I have no redundant entries but I want the
    # queryset ordering too .. need to make it a queryset for so many reasons...

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    呃,

    return Geom.objects.filter(geomrelation__in=grs)
    

    【讨论】:

    • 如果有人有什么要补充的或有任何反对意见或意见,我会暂时搁置一下。
    【解决方案2】:

    如果您的 Geom 类具有 generic.GenericRelation() 属性,您可以通过标准的向后关系获取对象。

    class Geom(models.Model):
        ...
        geom_relations = generic.GenericRelation(GeomRelation)
    

    这是仅限 Python 的属性,不需要更改数据库。现在要获取 geom_relations,您只需:

    geom.geom_relations.all()
    

    【讨论】:

      【解决方案3】:

      如果您将一个 QuerySet 对象作为另一个过滤器参数传递,ORM 将使用嵌套的 select 语句。最好在过滤器查找中桥接表关系;然后 ORM 将在 JOIN 上使用一个简单的 WHERE 子句,无论如何它都必须这样做。性能差异显着:

      In [2]: from django.db import connection
      In [3]: from app.models import *
      In [4]: ct = ContentType.objects.get_for_model(Thing)
      In [5]: grs = GeomRelation.objects.filter( content_type=ct, object_id=2 )
      In [6]: 
      In [7]: # slow method
      In [8]: list(Geom.objects.filter(geomrelation__in=grs));
      In [9]: connection.queries[-1]
      Out[9]: 
      {'sql': u'SELECT "app_geom"."id" FROM "app_geom" INNER JOIN "app_geomrelation" ON ("app_geom"."id" = "app_geomrelation"."geom_id") WHERE "app_geomrelation"."id" IN (SELECT U0."id" FROM "app_geomrelation" U0 WHERE (U0."content_type_id" = 10  AND U0."object_id" = 2 ))',
       'time': '0.140'}
      In [10]: 
      In [11]: # fast method
      In [12]: list(Geom.objects.filter(geomrelation__content_type=ct,
         ....:                         geomrelation__object_id=2));
      In [13]: connection.queries[-1]
      Out[13]: 
      {'sql': u'SELECT "app_geom"."id" FROM "app_geom" INNER JOIN "app_geomrelation" ON ("app_geom"."id" = "app_geomrelation"."geom_id") WHERE ("app_geomrelation"."object_id" = 2  AND "app_geomrelation"."content_type_id" = 10 )',
       'time': '0.001'}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-13
        • 1970-01-01
        • 2021-01-14
        • 2018-11-21
        • 2019-07-23
        • 2019-08-27
        • 2018-05-15
        相关资源
        最近更新 更多