Django通用关系和ORM查询

han*_*ims 7 sql django orm generic-relationship

说我有以下型号:

class Image(models.Model):
    image   = models.ImageField(max_length=200, upload_to=file_home)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

class Article(models.Model):
    text = models.TextField()
    images = generic.GenericRelation(Image)

class BlogPost(models.Model):
    text = models.TextField()
    images = generic.GenericRelation(Image)
Run Code Online (Sandbox Code Playgroud)

找到所有至少附有一个Image的文章的处理器和内存最有效的方法是什么?

我这样做了:

Article.objects.filter(pk__in=Image.objects.filter(content_type=ContentType.objects.get_for_model(Article)).values_list('object_id', flat=True))
Run Code Online (Sandbox Code Playgroud)

哪个有效,但除了丑陋之外需要永远.

我怀疑使用原始SQL有一个更好的解决方案,但这超出了我的范围.对于它的价值,上面生成的SQL如下:

 SELECT `issues_article`.`id`, `issues_article`.`text` FROM `issues_article` WHERE `issues_article`.`id` IN (SELECT U0.`object_id` FROM `uploads_image` U0 WHERE U0.`content_type_id` = 26 ) LIMIT 21
Run Code Online (Sandbox Code Playgroud)

编辑: czarchaic的建议有更好的语法,但更糟(更慢)的性能.他的查询生成的SQL如下所示:

SELECT DISTINCT `issues_article`.`id`, `issues_article`.`text`, COUNT(`uploads_image`.`id`) AS `num_images` FROM `issues_article` LEFT OUTER JOIN `uploads_image` ON (`issues_article`.`id` = `uploads_image`.`object_id`) GROUP BY `issues_article`.`id` HAVING COUNT(`uploads_image`.`id`) > 0  ORDER BY NULL LIMIT 21
Run Code Online (Sandbox Code Playgroud)

编辑: Jarret Hardie的万岁!这是他应该明显的解决方案生成的SQL:

SELECT DISTINCT `issues_article`.`id`, `issues_article`.`text` FROM `issues_article` INNER JOIN `uploads_image` ON (`issues_article`.`id` = `uploads_image`.`object_id`) WHERE (`uploads_image`.`id` IS NOT NULL AND `uploads_image`.`content_type_id` = 26 ) LIMIT 21
Run Code Online (Sandbox Code Playgroud)

Jar*_*die 6

由于泛型关系,您应该能够使用传统的查询集语义来查询此结构以获得反向关系:

Article.objects.filter(images__isnull=False)
Run Code Online (Sandbox Code Playgroud)

这将为任何Article与多个Images 相关的s 生成重复项,但您可以使用distinct()QuerySet方法消除它:

Article.objects.distinct().filter(images__isnull=False)
Run Code Online (Sandbox Code Playgroud)