簡體   English   中英

Django 圖片上傳和調整大小

[英]Django Image upload and resize

我有一個帶有圖像字段的標准 Django 表單。 上傳圖片時,我想確保圖片不大於 300 像素 x 300 像素。 這是我的代碼:

def post(request):
    if request.method == 'POST':
        instance = Product(posted_by=request.user)
        form = ProductModelForm(request.POST or None, request.FILES or None)
        if form.is_valid():
           new_product = form.save(commit=False)
           if 'image' in request.FILES:
              img = Image.open(form.cleaned_data['image'])
              img.thumbnail((300, 300), Image.ANTIALIAS)

              # this doesnt save the contents here...
              img.save(new_product.image)

              # ..because this prints the original width (2830px in my case)
              print new_product.image.width

我面臨的問題是,我不清楚如何將Image類型轉換為 ImageField 類型。

從 ImageField 的保存方法的文檔中:

注意內容參數應該是 django.core.files.File 的實例,而不是 Python 的內置文件 object。

This means you would need to convert the PIL.Image ( img ) to a Python file object, and then convert the Python object to a django.core.files.File object. 像這樣的東西(我沒有測試過這段代碼)可能會起作用:

img.thumbnail((300, 300), Image.ANTIALIAS)

# Convert PIL.Image to a string, and then to a Django file
# object. We use ContentFile instead of File because the
# former can operate on strings.
from django.core.files.base import ContentFile
djangofile = ContentFile(img.tostring())
new_product.image.save(filename, djangofile)

那里有 go,只需更改一點以滿足您的需要:

class PhotoField(forms.FileField, object):

    def __init__(self, *args, **kwargs):
        super(PhotoField, self).__init__(*args, **kwargs)
        self.help_text = "Images over 500kb will be resized to keep under 500kb limit, which may result in some loss of quality"

    def validate(self,image):
        if not str(image).split('.')[-1].lower() in ["jpg","jpeg","png","gif"]:
            raise ValidationError("File format not supported, please try again and upload a JPG/PNG/GIF file")

    def to_python(self, image):
        try:
            limit = 500000
            num_of_tries = 10
            img = Image.open(image.file)
            width, height = img.size
            ratio = float(width) / float(height)

            upload_dir = settings.FILE_UPLOAD_TEMP_DIR if settings.FILE_UPLOAD_TEMP_DIR else '/tmp'
            tmp_file = open(os.path.join(upload_dir, str(uuid.uuid1())), "w")
            tmp_file.write(image.file.read())
            tmp_file.close()

            while os.path.getsize(tmp_file.name) > limit:
                num_of_tries -= 1
                width = 900 if num_of_tries == 0 else width - 100
                height = int(width / ratio)
                img.thumbnail((width, height), Image.ANTIALIAS)
                img.save(tmp_file.name, img.format)
                image.file = open(tmp_file.name)
                if num_of_tries == 0:
                    break                    
        except:
            pass
        return image

來源: http://james.lin.net.nz/2012/11/19/django-snippet-reduce-image-size-during-upload/

這是一個可以解決這個問題的應用程序: django-smartfields

from django.db import models

from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor

class Product(models.Model):
    image = fields.ImageField(dependencies=[
        FileDependency(processor=ImageProcessor(
            scale={'max_width': 300, 'max_height': 300}))
    ])

在這里嘗試我的解決方案: https://stackoverflow.com/a/25222000/3731039

強調

  • 使用 Pillow 進行圖像處理(需要兩個包:libjpeg-dev、zlib1g-dev)
  • 使用 Model 和 ImageField 作為存儲
  • 使用 HTTP POST 或 PUT 與 multipart/form
  • 無需手動將文件保存到磁盤。
  • 創建多個分辨率並存儲它們的尺寸。

你可以使用我的庫django-sizedimagefield ,它沒有額外的依賴並且使用起來非常簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM