2

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

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使用sorl-thumbnaildjango-imagekit或以任何其他方式调整图像的大小以具有 470px 的宽度和自动高度?

4

1 回答 1

0

如果你想使用 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).

请务必查看示例以获取更多信息。


如果你觉得这种方法不是你想要的样子,或者你的存储速度很慢,那么使用 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="..." />

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

于 2016-09-01T17:27:37.740 回答