[英]How to resize image and save it - django
I have an app that for storing uploaded files (images, zip, videos..etc). 我有一个用于存储上传文件(图像,zip,视频等)的应用。 I use model FileField to handle the upload. 我使用FileField模型处理上传。 The thing is when upload image I want to resize the image and save it in another field (thumb) in the model. 问题是当我上载图像时,我想调整图像的大小并将其保存在模型的另一个字段(缩略图)中。
here is my models.py 这是我的models.py
class Files(models.Model):
file = models.FileField(upload_to=upload_path())
thumb = models.CharField(max_length=255,default=None,blank=True , null=True)
user = models.ForeignKey(User, null=True,blank=True)
date = models.DateTimeField('date added',blank=True, null=True)
The file is for store the original file url, and the thumb is to store the thumbnail url. 该文件用于存储原始文件的URL, 拇指用于存储缩略图的URL。
I know we can use PIL to do the resize, but I am novice in python, I don't how can I use it and save it in the app. 我知道我们可以使用PIL进行大小调整,但是我是python的新手,我不知道如何使用它并将其保存在应用程序中。
It's a module I wrote for my flask application website but you can change it for Django application and use it. 这是我为flask应用程序网站编写的模块,但是您可以将其更改为Django应用程序并使用。 It creates thumbnails and crops images. 它创建缩略图并裁剪图像。 Pretty useful for me: 对我来说非常有用:
"""
usage: <img src="{{ thumbnail('files/'+media.path, '150x150') }}" alt="" />
"""
# python imports
import os
import errno
import traceback
try:
from PIL import Image, ImageOps
except ImportError:
raise RuntimeError('Image module of PIL needs to be installed')
class Thumbnail(object):
def __init__(self, app=None):
if app is not None:
self.init_app(self.app)
else:
self.app = None
def init_app(self, app):
self.app = app
if not self.app.config.get('MEDIA_FOLDER', None):
raise RuntimeError('You\'re using the flask-thumbnail app '
'without having set the required MEDIA_FOLDER setting.')
if not self.app.config.get('THUMBNAIL_FOLDER', None):
raise RuntimeError(
'You didn\'t set THUMBNAIL_FOLDER setting.')
app.config.setdefault('THUMBNAIL_FOLDER', os.path.join(self.app.config['MEDIA_FOLDER'], 'thumbnail'))
app.config.setdefault('MEDIA_URL', '/media/')
app.config.setdefault('THUMBNAIL_URL', os.path.join(self.app.config['MEDIA_URL'], 'thumbnail'))
app.jinja_env.globals['thumbnail'] = self.thumbnail
def thumbnail(self, img_url, size, crop=None, bg=None, quality=92):
"""
:param img_url: url img - '/assets/media/summer.jpg'
:param size: size return thumb - '100x100'
:param crop: crop return thumb - 'fit' or None
:param bg: tuple color or None - (255, 255, 255, 0)
:param quality: JPEG quality 1-100
:return: :thumb_url:
"""
try:
width, height = [int(x) for x in size.split('x')]
url_path, img_name = os.path.split(img_url)
name, fm = os.path.splitext(img_name)
miniature = self._get_name(name, fm, size, crop, bg, quality)
original_filename = os.path.join(
self.app.config['MEDIA_FOLDER'],
url_path,
img_name)
thumb_filename = os.path.join(
self.app.config['THUMBNAIL_FOLDER'],
miniature)
# create folders
self._get_path(thumb_filename)
thumb_url = os.path.join(
self.app.config['THUMBNAIL_URL'],
miniature)
if os.path.exists(thumb_filename):
return thumb_url
elif not os.path.exists(thumb_filename):
thumb_size = (width, height)
try:
image = Image.open(original_filename)
except IOError:
return None
if crop == 'fit':
img = ImageOps.fit(image, thumb_size, Image.ANTIALIAS)
else:
img = image.copy()
img.thumbnail((width, height), Image.ANTIALIAS)
if bg:
img = self._bg_square(img, bg)
img.save(thumb_filename, image.format, quality=quality)
return thumb_url
except Exception, e:
traceback.print_exc()
print(e.message)
@staticmethod
def _bg_square(img, color=0xff):
size = (max(img.size),) * 2
layer = Image.new('L', size, color)
layer.paste(
img, tuple(map(lambda x: (x[0] - x[1]) / 2, zip(size, img.size))))
return layer
@staticmethod
def _get_path(full_path):
directory = os.path.dirname(full_path)
try:
if not os.path.exists(full_path):
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
@staticmethod
def _get_name(name, fm, *args):
for v in args:
if v:
name += '_%s' % v
name += fm
return name
This is how I make it work. 这就是我的工作方式。
from django.core.files.uploadedfile import InMemoryUploadedFile
def create_thumbnail(obj, ext=None):
imaged, imgformat = resize_and_crop(obj.file, (150, 150),crop_type='middle' )
thumb_io = BytesIO()
imaged.save(thumb_io, format=imgformat, quality=92)
new_file_name = u'thumb-' + str(obj.file.name)
thumbfile = InMemoryUploadedFile(thumb_io,
u"thumb", # important to specify field name here
new_file_name,
ext,
thumb_io,
None)
return thumbfile
class Files(models.Model):
file = models.FileField(upload_to=upload_path())
thumb = models.FileField(max_length=255,default=None,blank=True , null=True)
user = models.ForeignKey(User, null=True,blank=True)
date = models.DateTimeField('date added',blank=True, null=True)
def save(self, *args, **kwargs):
self.url = create_thumbnail(self, ext)
return super(MediaUpload, self).save(*args, **kwargs)
The resize_and_crop() was refer to this excellent script . resize_and_crop()引用了这个出色的脚本 。
The point at here is using the InMemoryUploadedFile to save the file in the memory and pass it to the FileField to do the rest of the job. 此处的重点是使用InMemoryUploadedFile将文件保存在内存中,然后将其传递给FileField来完成其余的工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.