django-sorl 使用模板语法时产生 IOError
我设置了django-sorl,但我觉得我可能忽略了一些简单的东西。我一直收到以下错误信息(TEMPLATE_DEBUG = True 和 THUMBNAIL_DEBUG = True)
请求方法:GET 请求网址: http://localhost:8000/events/edit/1
Django版本:1.2.4 异常类型: TemplateSyntaxError 异常值:
在渲染时捕获到IOError: (2, '没有这样的文件或目录')
异常位置: /usr/lib/python2.6/site-packages/django/core/files/storage.py 的_open, 第137行
Python可执行文件: /usr/bin/python Python版本: 2.6.4
我正在运行一个redis服务器... 我的sorl配置是:
settings.py -省略-:
TEMPLATE_DEBUG = DEBUG
THUMBNAIL_DEBUG = DEBUG
THUMBNAIL_KVSTORE = 'sorl.thumbnail.kvstores.redis_kvstore.KVStore'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'sorl.thumbnail',
)
models.py -省略-:
from sorl.thumbnail import ImageField
...
path = ImageField(
_('Image'),
upload_to='event/%Y/%m/%d/%H',
)
...
template.html -省略-:
{% load thumbnail %}
...
{% thumbnail image "200x100" as im %}
<img src="{{ im.url }}" alt="{{ im.name }}"/>
{% endthumbnail %}
...
我觉得我快解决了,因为在缓存文件夹里确实有文件被创建
sh> find static/cache/ -type f
static/cache/db/ac/dbac605942d9651eb25f16cf05f5e672.jpg
static/cache/82/bc/82bcdd2ab079187c6b6110cb0e0c1505.jpg
static/cache/07/77/077784411739d4f8b1758255783388ec.jpg
当我打开这些文件时,它们是我按需请求的图片。看起来在尝试打开图片以显示时出错了。还有一点要注意的是,如果我只是用以下语法显示图片,它就能正常工作(没有使用sorl):
正常工作的template.html(没有sorl,所以...没有缩略图) -省略-:
<img src="{{ MEDIA_URL}}{{ image.path }}" alt="{{ image.name }}"/>
关键是;我确实需要在图片前加上{{ MEDIA_URL }}标签才能显示(我不确定这是否与我在使用sorl时遇到的错误有关,还是只是个误导)。
最后,关于原始错误的一些小细节(它们来自生成的TemplateSyntaxError页面 - 最后5条)。
# /var/project/src/lib/sorl/thumbnail/base.py in get_thumbnail
36. thumbnail = ImageFile(name, default.storage)
37. cached = default.kvstore.get(thumbnail)
38. if cached:
39. return cached
40. if not thumbnail.exists():
41. # We have to check exists() because the Storage backend does not
42. # overwrite in some implementations.
43. source_image = default.engine.get_image(source) ...
44. # We might as well set the size since we have the image in memory
45. size = default.engine.get_image_size(source_image)
46. source.set_size(size)
47. self._create_thumbnail(source_image, geometry_string, options,
48. thumbnail)
49. # If the thumbnail exists we don't create it, the other option is
▼ Local vars Variable Value cached None file_ <EventImage: TestImage> geometry_string u'200x100' key 'format' name 'cache/24/69/246986cc89951f1d37235b8f0dec0a54.jpg' options {'colorspace': 'RGB', 'crop': False, 'format': 'JPEG', 'quality': 95, 'upscale': True} self <sorl.thumbnail.base.ThumbnailBackend object at 0x7f5b885f2c10> source <sorl.thumbnail.images.ImageFile object at 0x7f5b885c81d0> thumbnail <sorl.thumbnail.images.ImageFile object at 0x7f5b8867f510> value 'JPEG'
# /var/project/src/lib/sorl/thumbnail/engines/pil_engine.py in get_image
5. from PIL import Image, ImageDraw
6. except ImportError:
7. import Image, ImageDraw
8.
9.
10. class Engine(EngineBase):
11. def get_image(self, source):
12. buf = StringIO(source.read()) ...
13. return Image.open(buf)
14.
15. def get_image_size(self, image):
16. return image.size
17.
18. def dummy_image(self, width, height):
▼ Local vars Variable Value self <sorl.thumbnail.engines.pil_engine.Engine object at 0x7f5b886cf450> source <sorl.thumbnail.images.ImageFile object at 0x7f5b885c81d0>
# /home/caronc/Development/cityattention/src/lib/sorl/thumbnail/images.py in read
114. return self._size
115.
116. @property
117. def url(self):
118. return self.storage.url(self.name)
119.
120. def read(self):
121. return self.storage.open(self.name).read() ...
122.
123. def write(self, content):
124. if not isinstance(content, File):
125. content = ContentFile(content)
126. self._size = None
127. return self.storage.save(self.name, content)
▼ Local vars Variable Value self <sorl.thumbnail.images.ImageFile object at 0x7f5b885c81d0>
# /usr/lib/python2.6/site-packages/django/core/files/storage.py in open
25. # These shouldn't be overridden by subclasses unless absolutely necessary.
26.
27. def open(self, name, mode='rb', mixin=None):
28. """
29. Retrieves the specified file from storage, using the optional mixin
30. class to customize what features are available on the File returned.
31. """
32. file = self._open(name, mode) ...
33. if mixin:
34. # Add the mixin as a parent class of the File returned from storage.
35. file.__class__ = type(mixin.__name__, (mixin, file.__class__), {})
36. return file
37.
38. def save(self, name, content):
▼ Local vars Variable Value mixin None mode 'rb' name u'TestImage' self <django.core.files.storage.FileSystemStorage object at 0x7f5b8867f3d0>
# /usr/lib/python2.6/site-packages/django/core/files/storage.py in _open
130. location = settings.MEDIA_ROOT
131. if base_url is None:
132. base_url = settings.MEDIA_URL
133. self.location = os.path.abspath(location)
134. self.base_url = base_url
135.
136. def _open(self, name, mode='rb'):
137. return File(open(self.path(name), mode)) ...
138.
139. def _save(self, name, content):
140. full_path = self.path(name)
141.
142. directory = os.path.dirname(full_path)
143. if not os.path.exists(directory):
▼ Local vars Variable Value mode 'rb' name u'TestImage' self <django.core.files.storage.FileSystemStorage object at 0x7f5b8867f3d0>
我在谷歌上搜索这个错误没有成功;我希望我的问题只是个小问题,因为除了模板显示外,其他一切都正常。
2 个回答
在你的模型里,有一个属性叫做 path
。这个 path
是定义为 ImageField
的,最终就是用这个路径来获取图片,以制作最终的缩略图。sorl.thumbnail
不会自动猜测你想要什么,所以你需要传递图片的 来源,在你的情况下,这个来源似乎是 image.path
。你提到在 __unicode__
方法中返回 self.image.path
似乎不太对,可能应该是 self.path
,如果你还是在谈论那个定义了 path
的模型的话。
这段文档在这个领域的说明有点薄弱,不过在我导入了Python调试工具后,我找到了问题所在。
这个问题有两个可能的解决办法。第一个解决办法是我修改了我的模板,变成了:
{% load thumbnail %}
...
{% thumbnail image.path "200x100" as im %}
<img src="{{ im.url }}" alt="{{ im.name }}"/>
{% endthumbnail %}
...
我猜问题可能还是出在我这边,特别是这个工具已经很稳定很久了。不过,那些遇到同样问题的人需要加上.path这个参数,这样就能避免我经历的麻烦。
另一个(虽然不是很好)选择是把这个加到你的models.py文件里,然后再直接引用图片(就像我在最开始的问题中做的那样)。
def __unicode__(self):
return self.image.path
当然,如果你想显示的事件对象并不是专门用来显示图片的,那这个方法就不太好。因此,第二个选项可能只在某些情况下适用。我建议还是用第一个解决办法。
这个解决办法适用于10.12.1补丁。
另外,为了说明我最开始的问题。我说静态图片被创建了,结果发现这是不正确的。虽然那些图片确实是我在页面上无法使用的图片的正确缩略图,但它们是从Django管理工具自动生成的。可能是在我尝试上传不同图片的时候(走错了方向)。:)