【问题标题】:Django ORM m2m limit to 1Django ORM m2m 限制为 1
【发布时间】:2013-02-02 23:08:54
【问题描述】:
# models.py
class Gallery(models.Model):
    images = models.ManyToManyField(Image, null=True, blank=True)

class Image(models.Model):
    image = models.ImageField()


# views.py
class GalleryIndex(ListView):
    model = Gallery

我需要为每个画廊获取缩略图,这是第一张/最后一张/任何图像。 如何在不调用第二个 SQL 查询的情况下将任何图库的图像限制为 1 作为自定义属性(不覆盖 Gallery.images)?

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

    多对多充当普通查询集的描述符,因此您可以通过 my_gallery.images.all()[0] 将查询限制为 1。

    【讨论】:

    • 这只是每个画廊的作品,而不是所有画廊的作品……我错了吗?
    【解决方案2】:

    我认为我没有正确理解您想要做什么,但下面的代码不适合您吗?

    class Gallery(models.Model):
        images = models.ManyToManyField(Image, null=True, blank=True)
    
        def get_thumb(self):
            return self.images.all()[0]
    

    或者可能是其他概念:

    class Gallery(models.Model):
        images = models.ManyToManyField(Image, null=True, blank=True)
        thumbnail = models.ImageField()
    
        def save(self, *args, **kwargs):
            self.thumbnail = self.images.all()[0].image
    

    (不过这里需要一些异常捕获)

    【讨论】:

    • 我想在单个 SQL 查询中选择画廊和他们的第一张图片作为他们的自定义属性。第一个示例仍然生成一个 + N 查询(​​其中 N 是画廊的数量)。由于缩略图选择的自定义逻辑,第二个示例在我的情况下不存在......
    • 它甚至不是选择,而是填充 ImageGallery 模型是完全独立和分离的(这就是为什么 images 字段可以为空)。通过提供queryset = Gallery.objects.prefetch_related('images').all() 来查看类,我已将 SQL 查询减少到两个……但仍然是 2 个查询,而不是一个。
    • 这仍然不能解释太多,但我会按照我描述的方式。最终将 Gallery.thumbnail 更改为 thumbnail_image = models.ForeignKey(Image, null=True) 其余的应该是更新数据的问题 - 信号或 save() 方法
    • 或者缓存是要走的路?
    【解决方案3】:

    我应该更好地阅读文档。标准 QuerySet API 不能有效地处理这种情况(annotate() 为每个父字段生成 GROUP BY 子句,这很慢)所以我提供了 extra() 方法和原始子查询。

    class GalleryIndex(ListView):
        queryset = Gallery.objects.extra(select={'thumb':
            """
            SELECT "image"
            FROM "app_image", "app_gallery_images"
            WHERE (
                "app_gallery"."id" = "app_gallery_images"."gallery_id"
                AND "app_gallery_images"."image_id" = "app_image"."id"
            )
            AND "app_image"."image" IS NOT NULL
            LIMIT 1
            """
        })
    

    这个查询集完全符合我的要求,因为 SorlImageField(和 ImageField)只需要文件名来表示模板中的缩略图。

    【讨论】:

      猜你喜欢
      • 2014-09-24
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      相关资源
      最近更新 更多