2010-06-27 26 views
2

假设我有一个代表现实生活中物体的几个型号:“”,“主席”,“室”整蛊Django的GenericRelation查询

我也有一个“集合”的模式,它代表了这些模型的一些记录集合。

每个模型都可以是多个集合的成员 - 因此,我还创建了一个“成员”模型,它表示一个对象是集合的成员。它的定义如下:

class Membership(models.Model): 
    content_type = models.ForeignKey(ContentType) 
    object_id  = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

    collection  = models.ForeignKey('Collection', related_name="members") 

我希望能够创造一个的QuerySet,其给出的集合,代表了其所有成员一个给定的模型。我知道我可以通过编程方式做到这一点,但我需要它在一个QuerySet,它可以过滤,排序等

编辑:

SELECT * FROM 
     (modelx INNER JOIN membership ON modelx.id = membership.object_id) 
    WHERE 
     (membership.collection_id=<my-collection-id> AND  
     membership.content_type_id=<modelx-type-id>) 

显然,这可以使用原始SQL来完成

但它可以使用Django查询语言来表示吗?

回答

2

看来我已经找到了解决方案,通过使用QuerySetextra方法:

def members_of_model(collection,cls): 
    cls_type = ContentType.objects.get_for_model(cls) 
    cm_tablename = CollectionMembership._meta.db_table 
    cls_tablename = cls._meta.db_table 
    return cls.objects.all().extra(tables=[cm_tablename], 
            where=[ '%s.content_type_id=%%s' % cm_tablename, 
              '%s.collection_id=%%s' % cm_tablename, 
              '%s.object_id=%s.id' % (cm_tablename, cls_tablename) ], 
            params=[cls_type.id,collection.id]) 

这将返回一个特定的模型,其中包含它们是一个特定集合成员的所有记录的有效查询集。

0

不,这是不可能的。查询集只能是单一模型类型。因此,您可以获取Membership对象的查询集并引用每个对象的content_object属性,这会为您提供相关对象,但无法直接在一个查询集中获取所有相关对象。

+1

我只希望查询集举行一个模型...... 我能改写这个问题的记录: 我可以查询模型X的所有记录,所以,存在着具有记录X作为其内容的会员资格对象和其“集合”字段中的特定集合? – adamk 2010-06-28 06:33:34

1

我实现的正是这种由上自定义管理器with_model方法的会员制模式的方式:

class CollectionMemberManager(models.Manager): 
    use_for_related_fields = True 

    def with_model(self, model): 
     return model._default_manager.filter(pk__in=self.filter(member_content_type=ContentType.objects.get_for_model(model)).values_list('member_object_id', flat=True)) 

CollectionMember是我相当于你Membership模型。有关更多上下文,请参阅the code in its entirety

+0

这是一个有效的答案,只有两个问题: (1)它确实需要额外的查询& (2)对于大集合使用pk__in并不总是有效 - 对于大集合(约1000个成员),生成的查询太长了。 – adamk 2010-06-28 06:35:08