我正在构建一个django网站,当我通过admin视图上传图像(模型为Photo)时,我想生成该图像的任意缩略图并将其保存到Thumbnail Image Field。 缩略图生成效果很好,但是当Photo模型尝试保存时,我得到的是我试图对已关闭的对象执行I / O操作:“对已关闭文件的I / O操作”。 堆栈跟踪追溯到对超类的调用,因此我认为它是通过generate_thumbnail函数实现的。
我在做什么错?任何帮助将不胜感激。
from PIL import Image
from io import BytesIO
from django.core.files.base import ContentFile
class Photo(models.Model):
photo=models.ImageField(upload_to='photos/',blank=True)
thumbnail = models.ImageField(upload_to='thumbs/', editable=False, null=True)
def save(self,*args,**kwargs):
if self.photo:
self.generate_thumbnail()
super(Photo, self).save(*args,**kwargs)
def generate_thumbnail(self):
img =Image.open(self.photo)
img.thumbnail([consts.THUMB_HEIGHT,consts.THUMB_WIDTH],Image.ANTIALIAS)
name = os.path.basename(self.photo.name)
thumb_name, thumb_ext = os.path.splitext(name)
thumb_ext=thumb_ext.lower()
outname="thumb_"+thumb_name+thumb_ext
if thumb_ext in ['.jpg','.jpeg']:
filetype='JPEG'
elif thumb_ext == '.gif':
filetype='GIF'
elif thumb_ext=='.png':
filetype = 'PNG'
else:
raise Exception("Failed to generate thumbnail. Is the filetype valid?")
temp_thumb=BytesIO()
img.save(temp_thumb,filetype)
temp_thumb.seek(0)
self.thumbnail.save(outname,ContentFile(temp_thumb.read()),save=False)
temp_thumb.close()
return True
因此,一天之后,相同的代码,不同的错误。现在,找不到该文件与temp目录中的文件。此错误的堆栈跟踪如下。
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/admin/coffins/photo/11/change/
Django Version: 2.1.5
Python Version: 3.7.2
Installed Applications:
['storages',
'coffins.apps.CoffinsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/blah/venv/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/blah/venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "/blah/venv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/options.py" in wrapper
604. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapped_view
142. response = view_func(request, *args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
44. response = view_func(request, *args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/sites.py" in inner
223. return view(request, *args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/options.py" in change_view
1640. return self.changeform_view(request, object_id, form_url, extra_context)
File "/blah/venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapper
45. return bound_method(*args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/utils/decorators.py" in _wrapped_view
142. response = view_func(request, *args, **kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/options.py" in changeform_view
1525. return self._changeform_view(request, object_id, form_url, extra_context)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/options.py" in _changeform_view
1564. self.save_model(request, new_object, form, not add)
File "/blah/venv/lib/python3.7/site-packages/django/contrib/admin/options.py" in save_model
1091. obj.save()
File "/blah/coffins/models.py" in save
62. super(Photo, self).save(*args,**kwargs)
File "/blah/venv/lib/python3.7/site-packages/django/db/models/base.py" in save
718. force_update=force_update, update_fields=update_fields)
File "/blah/venv/lib/python3.7/site-packages/django/db/models/base.py" in save_base
748. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/blah/venv/lib/python3.7/site-packages/django/db/models/base.py" in _save_table
809. for f in non_pks]
File "/blah/venv/lib/python3.7/site-packages/django/db/models/base.py" in <listcomp>
809. for f in non_pks]
File "/blah/venv/lib/python3.7/site-packages/django/db/models/fields/files.py" in pre_save
288. file.save(file.name, file.file, save=False)
File "/blah/venv/lib/python3.7/site-packages/django/db/models/fields/files.py" in save
87. self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "/blah/venv/lib/python3.7/site-packages/django/core/files/storage.py" in save
49. return self._save(name, content)
File "/blah/venv/lib/python3.7/site-packages/django/core/files/storage.py" in _save
255. file_move_safe(content.temporary_file_path(), full_path)
File "/blah/venv/lib/python3.7/site-packages/django/core/files/move.py" in file_move_safe
56. with open(old_file_name, 'rb') as old_file:
Exception Type: FileNotFoundError at /admin/coffins/photo/11/change/
Exception Value: [Errno 2] No such file or directory: '/var/folders/s6/w4dbxvkj0ng4l7s5_pqd_mxr0000gn/T/tmpunp8vg4b.upload.jpg'
答案 0 :(得分:0)
我对此的解决方案最终是下载一个做到这一点的库: stdimage正是按照我想要的方式做的-在图片上传时会建立一个编码器定义大小的缩略图,并将其保存到应用程序的存储空间中(在我的情况下为S3)。 那里的大多数库似乎都是按需生成缩略图的,并且缩略图是在模板而不是模型中指定的。这通常需要某种方法。对于我的需求,这不是最佳选择。在查看了此插件的代码后,它们涵盖了我在这里没有处理过的许多极端情况,并且不愿意花时间独自讲述。
感谢所有提供帮助的人!