Question

Je souhaite obtenir tous les objets Geom associés à un objet content_object (voir la fonction que j'essaie de créer en bas, 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...
Était-ce utile?

La solution

Duh,

return Geom.objects.filter(geomrelation__in=grs)

Autres conseils

Si votre classe Geom a une propriété generic.GenericRelation (), vous pouvez obtenir les objets via une relation vers l'arrière standard.

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

Ceci est une propriété Python uniquement, qui ne nécessite pas de modification de la base de données. Maintenant, pour obtenir les relations geom, il suffit de faire:

geom.geom_relations.all()

Si vous transmettez un objet QuerySet en tant qu'argument de filtre pour un autre, l'ORM utilisera des instructions select imbriquées. Il est préférable de relier les relations entre les tables dans les recherches de filtres. alors l'ORM utilisera une simple clause WHERE sur le JOIN, ce qu'il doit faire de toute façon. La différence de performance est significative:

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'}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top