【问题标题】:Django channels to resize an imageDjango 通道调整图像大小
【发布时间】:2017-01-01 01:39:48
【问题描述】:

我有一个照片模型,有两个图像字段。一个用于原始图像,另一个用于原始图像的调整大小版本。

class Photo(models.Model):
    user = models.ForeignKey(User)
    image_original = models.ImageField(
        upload_to=get_upload_file_name,
        width_field="image_original_width",
        height_field="image_original_height",
        blank=True
    )
    image_original_width = models.IntegerField(default=0)
    image_original_height = models.IntegerField(default=0)
    image_470 = models.ImageField(
        upload_to=get_upload_file_name,
        width_field="image_470_width",
        height_field="image_470_height",
        blank=True
    )
    image_470_width = models.IntegerField(default=0)
    image_470_height = models.IntegerField(default=0)

我选择 django-channles 的原因是因为我已经将它用于 websocket 目的,并且在文档中他们说 "... 而且,除此之外,还有很多非关键任务可以应用在发送响应之前可以轻松卸载 - 例如将内容保存到缓存中或缩略图新上传的图像。”

如何使用 django-channels 调整图像大小,使其宽度为 470 像素,并使用 sorl-thumbnaildjango-imagekit 自动调整高度> 还是以其他方式?

【问题讨论】:

  • 我看不出通道与调整图像大小有什么关系。您能否详细说明为什么要使用 django-channels 来执行此任务,这是什么意思?另外,你对 sorl-thumbnail 死心了吗?为同一图像的不同版本设置单独的模型字段的模型似乎更符合 django-imagekit 的要求。
  • @LudwikTrammer django-imagekit 看起来很有希望。谢谢你。我肯定会试一试。我选择 django-channles 的原因是因为我已经将它用于 websocket 目的,并且在文档中他们说“而且,除此之外,应用程序可以轻松卸载许多非关键任务,直到响应之后已发送 - 例如将内容保存到缓存中或缩略图新上传的图像。”。
  • 感谢您的回复。我建议将此信息添加到您的原始问题中。
  • @LudwikTrammer 好的。谢谢。

标签: django django-models sorl-thumbnail django-imagekit django-channels


【解决方案1】:

如果你想使用 sorl-thumbnail,那么你不需要在你的模型代码中做任何事情。只要有这样的课程:

class Photo(models.Model):
    user = models.ForeignKey(User)
    image = models.ImageField(
        upload_to=get_upload_file_name,
        width_field="width",
        height_field="height",
        blank=True
    )
    width = models.IntegerField(default=0)
    height = models.IntegerField(default=0)

当您需要 470 像素的图片时,请在模板中执行以下操作:

{% load thumbnail %}
...

{# Specifying width only here. #}
{# If you want a height constraint as well use e.g. "470x1000". #}
{% thumbnail photo.image "470" as im %}
    <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}

就是这样 — sorl-thumbnail 将负责其余的工作(在第一次请求时缩放、处理缓存等)。它按需运行,即调整大小将在第一次访问时完成(当遇到模板标签时)——这通常很好。您应该记住的唯一一件事是,如果您的存储速度很慢,sorl-thumbnail 将无法正常工作。如果您将媒体存储在本地驱动器上 - 这很好。如果您的存储后端是 Amazon S3 - 不要这样做。

方便的部分是您是否需要其他缩略图大小,您只需在模板代码中告诉 sorl-thumnail 您需要它们。无需更改模型。

如果您想确保缩略图是使用 sorl-thumbnail 预先生成的,您可以显式调用 get_thumbnail 或使用,例如Celery 任务将为您运行 get_thumbnail(忽略结果),例如

@app.task
def ensure_thumbnail(photo_pk, size="470"):
    photo = Photo.objects.get(pk=photo_pk)
    get_thumbnail(photo.image, size)

每当您看到新上传的内容时,请致电ensure_thumbnail.delay(photo.pk)

请务必查看the examples 了解更多信息。


如果您觉得这种方法不是您想要的样子,或者您的存储速度很慢,那么请使用 django-imagekit。我对它不太熟悉(我自己没有在生产中使用过),但根据文档它看起来像这样:

您的模型如下所示:

from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFit
...

class Photo(models.Model):
    user = models.ForeignKey(User)
    image_original = models.ImageField(
        upload_to=get_upload_file_name,
        width_field="image_original_width",
        height_field="image_original_height",
        blank=True
    )
    image_original_width = models.IntegerField(default=0)
    image_original_height = models.IntegerField(default=0)
    # I haven't found a way to not specify the height.
    image_470 = ImageSpecField(source="image_original",
                               processors=[ResizeToFit(470, 1000)],
                               format="JPEG")

(像 sorl-thumbnail 一样,这实际上不会创建数据库字段。如果您绝对想要一个完全托管的独立图像文件,具有自己的数据库字段 - 似乎您最好的选择是在 Photo.save 中显式生成缩略图使用裸 Pillow 库。)

那么就简单明了:

<img src="{{ photo.image_470.url }}"
     width="{{ photo.image_470.width }}"
     height="{{ photo.image_470.height }}"
     alt="..." />

请务必查看文档 on caching,其中解释了缓存的工作原理(以及异步生成缩略图,您是否希望这样)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2013-07-04
    • 2012-12-18
    • 2011-03-29
    相关资源
    最近更新 更多