[英]How to save pillow image object to Django ImageField?
縮略圖有一個 Django model 像:
class Thumb(models.Model):
thumb = models.ImageField(upload_to='uploads/thumb/', null=True, default=None)
視圖生成一個帶有pillow
package 的縮略圖,並且應該將其保存在Thumb
實例中,使用如下代碼:
image.thumbnail((50, 50))
inst.thumb.save('thumb.jpg', ???)
為inst.thumb.save
制作image
數據的正確方法是什么???
?
我能夠讓下面的工作:
thumb_temp = NamedTemporaryFile()
image.save(thumb_temp, 'JPEG', quality=80)
thumb_temp.flush()
inst.thumb.save('thumb.jpg', File(thumb_temp))
thumb_temp.close() # Probably required to ensure temp file delete at close
但是寫一個臨時文件只是為了將內部數據傳遞給inst.thumb.save
似乎相當笨拙,所以我想知道是否有更優雅的方法來做到這一點。 Django class NamedTemporaryFile
的文檔。
這是一個工作示例(Python3,django 1.11),它從Model.ImageField
獲取圖像,使用 PIL (Pillow) 對其執行調整大小操作,然后將生成的文件保存到同一個 ImageField。 希望這應該很容易適應您必須對模型圖像進行的任何處理。
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.files.base import ContentFile
from PIL import Image
IMAGE_WIDTH = 100
IMAGE_HEIGHT = 100
def resize_image(image_field, width=IMAGE_WIDTH, height=IMAGE_HEIGHT, name=None):
"""
Resizes an image from a Model.ImageField and returns a new image as a ContentFile
"""
img = Image.open(image_field)
if img.size[0] > width or img.size[1] > height:
new_img = img.resize((width, height))
buffer = BytesIO()
new_img.save(fp=buffer, format='JPEG')
return ContentFile(buffer.getvalue())
#assuming your Model instance is called `instance`
image_field = instance.image_field
img_name = 'my_image.jpg'
img_path = settings.MEDIA_ROOT + img_name
pillow_image = resize_image(
image_field,
width=IMAGE_WIDTH,
height=IMAGE_HEIGHT,
name=img_path)
image_field.save(img_name, InMemoryUploadedFile(
pillow_image, # file
None, # field_name
img_name, # file name
'image/jpeg', # content_type
pillow_image.tell, # size
None) # content_type_extra
)
您可以為您的模型創建 pre_save 接收器:
from io import BytesIO
from functools import partial
from django.db import models
from django.core.files.uploadedfile import InMemoryUploadedFile
from PIL import Image
class Article(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=120, unique=True)
image = models.ImageField(
upload_to=upload_image_location
)
thumbnail_image = models.ImageField(
upload_to=partial(upload_image_location, thumbnail=True),
editable=False, blank=True
)
def create_thumbnail(self):
image = Image.open(self.image.file.file)
image.thumbnail(size=(310, 230))
image_file = BytesIO()
image.save(image_file, image.format)
self.thumbnail_image.save(
self.image.name,
InMemoryUploadedFile(
image_file,
None, '',
self.image.file.content_type,
image.size,
self.image.file.charset,
),
save=False
)
@receiver(models.signals.pre_save, sender=Article)
def prepare_images(sender, instance, **kwargs):
if instance.pk:
try:
article = Article.objects.get(pk=instance.pk)
old_image = article.image
old_thumbnail_image = article.thumbnail_image
except Article.DoesNotExist:
return
else:
new_image_extension = os.path.splitext(instance.image.name)[1]
if old_image and not old_image.name.endswith(new_image_extension):
old_image.delete(save=False)
old_thumbnail_image.delete(save=False)
if not instance.thumbnail_image or not instance.image._committed:
instance.create_thumbnail()
圖像的縮略圖是使用Pillow在create_thumbnail
方法中創建的。 此方法適用於django-storages並將縮略圖保存在自定義存儲中,名稱為“article_slug_thumbnail.jpeg”。
我的 upload_image_location 方法:
def upload_image_location(instance, filename, thumbnail=False):
_, ext = os.path.splitext(filename)
return f'articles/{instance.slug}{f"_thumbnail" if thumbnail else ""}{ext}'
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
image = models.ImageField(default = 'default.jpg',upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super().save()
img = Image.open(self.image.path)
if img.height >300 or img.width >300:
oputput_size = (300,300)
img.thumbnail(oputput_size)
img.save(self.image.path)
from io import BytesIO
from PIL import Image
from django.core.files.images import ImageFile
import requests
img_url = 'https://cdn.pixabay.com/photo/2021/08/25/20/42/field-6574455__340.jpg'
res = Image.open(requests.get(img_url, stream=True).raw)
filename = 'sample.jpeg'
img_object= ImageFile(BytesIO(res.fp.getvalue()), name=filename)
// django_image_field = img_object
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.