简体   繁体   English

如何在将 ImageField 图像保存到 python Django 模型之前调整其大小

[英]How to resize an ImageField image before saving it in python Django model

I am trying to implement a Django ImageField class function for resizing images however I am not certain where this function accepts my new image dimensions我正在尝试实现一个 Django ImageField 类函数来调整图像大小,但是我不确定这个函数在哪里接受我的新图像尺寸

Running on Linux and Python 3.7在 Linux 和 Python 3.7 上运行

I've had a look at this documentation, but can't quite make sense of it: https://docs.djangoproject.com/en/1.11/_modules/django/db/models/fields/files/#ImageField我看过这个文档,但不太理解它: https : //docs.djangoproject.com/en/1.11/_modules/django/db/models/fields/files/#ImageField

I'd really appreciate it if someone can show me an example of how to use this function.如果有人可以向我展示如何使用此功能的示例,我将不胜感激。

EDIT编辑

I haven't successfully managed to resize my image dimensions yet, which is what i am trying to achieve.我还没有成功地调整我的图像尺寸,这就是我想要实现的。 How may I resize this image before I save it given it is being fetched by ImageField (I found the update_dimensions_fields class function for ImageField however i cant figure out how to use it)我怎么可能我之前调整这个图像存起来给它正在被取出ImageField (我发现update_dimensions_fields类功能ImageField但我无法弄清楚如何使用它)

class Posts(models.Model):
    title = models.CharField(max_length=200, blank=True)
    body = models.TextField(blank=True)
    created_at = models.DateTimeField(default=datetime.datetime.now)
    post_image = models.ImageField(upload_to=get_image_path, blank=True, null=True)

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        # I would like to use the function beneath to resize my images before I save them to my database
        self.post_image.update_dimension_fields(self, instance, force=False, *args, **kwargs)

        super().save(*args, **kwargs) # Call the "real" save() method.

    class Meta:
        verbose_name_plural = "Posts"

You could use the django-resized library.您可以使用django-resized库。 It resizes images when uploaded and stores them for you.它会在上传时调整图像大小并为您存储它们。

Usage用法

from django_resized import ResizedImageField

class Posts(models.Model):
    title = models.CharField(max_length=200, blank=True)
    body = models.TextField(blank=True)
    created_at = models.DateTimeField(default=datetime.datetime.now)
    post_image = ResizedImageField(size=[500, 300], upload_to=get_image_path, blank=True, null=True)

    def __str__(self):
        return self.title

Options选项

  • size - max width and height, for example [640, 480] size - 最大宽度和高度,例如 [640, 480]
  • crop - resize and crop.裁剪- 调整大小和裁剪。 ['top', 'left'] - top left corner, ['middle', - 'center'] is center cropping, ['bottom', 'right'] - crop right bottom corner. ['top', 'left'] - 左上角,['middle', - 'center'] 是中心裁剪,['bottom', 'right'] - 裁剪右下角。
  • quality - quality of resized image 1..100质量- 调整大小的图像质量 1..100
  • keep_meta - keep EXIF and other meta data, default True keep_meta - 保留 EXIF 和其他元数据,默认为 True
  • force_format - force the format of the resized image, available formats are the one supported by pillow, default to None force_format - 强制调整图像的格式,可用格式为pillow支持的格式,默认为None
**

This will work **First of all install "PIL Fork" using 'pip install pillow这将起作用**首先使用'pip install Pillow安装“PIL Fork”

from PIL import Image


def __str__(self):
    return self.title


def save(self, *args, **kwargs):
    super(Posts, self).save(*args, **kwargs)
    imag = Image.open(self.post_image.path)
    if imag.width > 400 or imag.height> 300:
        output_size = (400, 300)
        imag.thumbnail(output_size)
        imag.save(self.post_image.path)
class Meta:
    verbose_name_plural = "Posts"

You can use this method to resize the image before saving it: (you need pip install pillow )您可以使用此方法在保存图像之前调整图像大小:(您需要pip install pillow

import os
from io import BytesIO
from PIL import Image as PilImage
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile

def resize_uploaded_image(image, max_width, max_height):
    size = (max_width, max_height)

    # Uploaded file is in memory
    if isinstance(image, InMemoryUploadedFile):
        memory_image = BytesIO(image.read())
        pil_image = PilImage.open(memory_image)
        img_format = os.path.splitext(image.name)[1][1:].upper()
        img_format = 'JPEG' if img_format == 'JPG' else img_format

        if pil_image.width > max_width or pil_image.height > max_height:
            pil_image.thumbnail(size)

        new_image = BytesIO()
        pil_image.save(new_image, format=img_format)

        new_image = ContentFile(new_image.getvalue())
        return InMemoryUploadedFile(new_image, None, image.name, image.content_type, None, None)

    # Uploaded file is in disk
    elif isinstance(image, TemporaryUploadedFile):
        path = image.temporary_file_path()
        pil_image = PilImage.open(path)

        if pil_image.width > max_width or pil_image.height > max_height:
            pil_image.thumbnail(size)
            pil_image.save(path)
            image.size = os.stat(path).st_size

    return image

Then use it in the clean method of the image field in your form:然后在表单中 image 字段的 clean 方法中使用它:

class ImageForm(forms.Form):
    IMAGE_WIDTH = 450
    IMAGE_HEIGHT = 450
    
    image = forms.ImageField()

    def clean_image(self):
        image = self.cleaned_data.get('image')
        image = resize_uploaded_image(image, self.IMAGE_WIDTH, self.IMAGE_HEIGHT)
        return image

To understand how the resize_uploaded_image method works, you may read about how Django handles uploaded files in the docs, here and here .要了解resize_uploaded_image方法的工作原理,您可以在此处此处的文档中阅读有关 Django 如何处理上传文件的信息

You can use the django-imagekit library.您可以使用django-imagekit库。

Installation安装

  1. Install Pillow .安装Pillow (If you're using an ImageField in Django, you should have already done this.) (如果你在 Django 中使用ImageField ,你应该已经这样做了。)
  2. pip install django-imagekit
  3. Add 'imagekit' to your INSTALLED_APPS list in your project's settings.py'imagekit'添加到项目settings.py INSTALLED_APPS列表中

Models.py模型.py

from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',
                                  processors=[ResizeToFill(100, 50)],
                                  format='JPEG',
                                  options={'quality': 60})

Pay attention to the source attribute of ImageSpecField which directs to the actual image field ( avatar in this case) as ImageSpecField are virtual in nature, you can read more about it here注意ImageSpecFieldsource属性,它指向实际的图像字段(在这种情况下是avatar ),因为 ImageSpecField 本质上是虚拟的,你可以在这里阅读更多关于它的信息

Using in your template在您的模板中使用

<img src="{{ profile.avatar_thumbnail.url }}" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM