我的Django项目中有一个带有头像字段的用户模型:
class User(AbstractBaseUser):
avatar = models.ImageField(
null=True,
blank=True,
upload_to='user/avatar/',
)
头像不是必需的,所以如果用户没有上传,我想使用默认图片。另一方面,我不想使用default
参数,以便能够在将来为所有用户更改默认头像:
class User(AbstractBaseUser):
avatar = models.ImageField(
null=True,
blank=True,
default='defaults/no-avatar.png',
upload_to='user/avatar/',
)
所以我最后写了一个get_avatar
方法,如果存在头像或者是默认静态图像的路径,则返回图像:
@property
def get_avatar(self):
if self.avatar:
return self.avatar
return '{0}defaults/no-avatar.png'.format(settings.STATIC_URL)
但在这种情况下,sorl-thumbnail
无法为默认图片生成缩略图
{% thumbnail user.get_avatar "46x46" crop="center" as im %}
<img title="{{ user }}" src="{{ im.url }}" class="img-circle" />
{% endthumbnail %}
并返回以下错误:
ERROR 2014-09-22 12:49:48,020 thumbnail :: Thumbnail tag failed:
Traceback (most recent call last):
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/templatetags/thumbnail.py", line 45, in render
return self._render(context)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/templatetags/thumbnail.py", line 97, in _render
file_, geometry, **options
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/base.py", line 56, in get_thumbnail
source_image = default.engine.get_image(source)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/engines/pil_engine.py", line 12, in get_image
buf = StringIO(source.read())
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/images.py", line 121, in read
return self.storage.open(self.name).read()
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 33, in open
return self._open(name, mode)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 159, in _open
return File(open(self.path(name), mode))
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 260, in path
raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
我尝试重写该方法,以便返回图像:
from django.core.files.images import ImageFile
@property
def get_avatar(self):
if self.avatar:
return self.avatar
return ImageFile(open(os.path.join(settings.STATIC_ROOT, 'defaults/no-avatar.png'), 'r'))
但是我遇到了类似的错误:
ERROR 2014-09-22 12:52:18,448 thumbnail :: Thumbnail tag failed:
Traceback (most recent call last):
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/templatetags/thumbnail.py", line 45, in render
return self._render(context)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/templatetags/thumbnail.py", line 97, in _render
file_, geometry, **options
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/base.py", line 56, in get_thumbnail
source_image = default.engine.get_image(source)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/engines/pil_engine.py", line 12, in get_image
buf = StringIO(source.read())
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/sorl/thumbnail/images.py", line 121, in read
return self.storage.open(self.name).read()
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 33, in open
return self._open(name, mode)
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 159, in _open
return File(open(self.path(name), mode))
File "/Users/vera/.virtualenvs/my_app/lib/python2.7/site-packages/django/core/files/storage.py", line 260, in path
raise SuspiciousFileOperation("Attempted access to '%s' denied." % name)
SuspiciousFileOperation: Attempted access to '/Users/vera/workspace/my-website/static/defaults/no-avatar.png' denied.
答案 0 :(得分:2)
sorl-thumbnail
使用storage functionality
。 Django委托决定如何以及在何处将文件存储到file storage system
。这是实际理解文件系统,打开和读取文件等内容的对象.Django附带了一个django.core.files.storage.FileSystemStorage类,它实现了基本的本地文件系统文件存储。默认情况下,Django使用MEDIA_ROOT和MEDIA_URL设置在本地存储文件。
所以在你的情况下,django尝试在MEDIA_ROOT下找到图像,但你已经将图像保存在STATIC_ROOT下。
如何修复
作为修补程序,您可以尝试在MEDIA_ROOT下移动图像,并在get_avatar方法中更改路径。 或者您可以尝试编写自定义存储,这将适用于两个文件夹。 Example custom storage