7

次のモデルがあるとします。

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)

少なくとも 1 つの画像が添付されているすべての記事を見つけるための最もプロセッサ効率とメモリ効率の良い方法は何ですか?

私はこれをやった:

Article.objects.filter(pk__in=Image.objects.filter(content_type=ContentType.objects.get_for_model(Article)).values_list('object_id', flat=True))

これは機能しますが、醜いだけでなく、永遠にかかります。

生の 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

編集: 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

編集:ジャレット・ハーディ万歳!彼の当然のはずだったソリューションによって生成された 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
4

2 に答える 2

6

一般的な関係のおかげで、逆関係の従来のクエリセットセマンティクスを使用してこの構造をクエリできるはずです。

Article.objects.filter(images__isnull=False)

Articleこれにより、複数のに関連するすべてのの重複が生成されますが、 QuerySetメソッドImageを使用してそれを排除できます。distinct()

Article.objects.distinct().filter(images__isnull=False)
于 2009-12-23T00:44:55.050 に答える