无法在Django开发环境中处理静态图片
我看过这篇文章(还有其他几篇相关的),但还是搞不清楚怎么显示图片,除非在html模板里硬编码一个指向网络服务上文件的链接。
在我的urls.py文件里有:
...
(r'^galleries/(landscapes)/(?P<path>.jpg)$',
'django.views.static.serve', {'document_root': settings.MEDIA_URL}),
...
这里的'landscapes'是我想要显示图片的相册之一。(还有其他几个相册。)
在views.py里,它用这样的代码调用模板:
...
<li><img src=160.jpg alt='' title='' /></li>
...
这段代码会把html里的图片链接解析成:
http://127.0.0.1:8000/galleries/landscapes/160.jpg
在settings.py里,我有:
MEDIA_ROOT = 'C:/siteURL/galleries/'
MEDIA_URL = 'http://some-good-URL/galleries/'
在我的文件系统里,有一个文件C:/siteURL/galleries/landscapes/160.jpg,我在http://some-good-URL/galleries/landscapes/160.jpg上也有同样的文件。
无论我在urls.py里用什么——MEDIA_ROOT还是MEDIA_URL(希望能从本地或网络服务器提供图片)——在浏览器的源代码里我得到的是:
<li><img src=160.jpg /></li>
浏览器里没有显示任何图片。
我到底哪里做错了呢?
3 个回答
可以把这个看作是之前两个答案的结合,两个答案都挺不错的。首先,你的正则表达式是错误的,正如Alex所指出的。我建议你把它设置成:
(r'^local_media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}), # static content
因为你可能还想提供css和js文件,而不仅仅是图片。这个正则表达式可以处理你可能想要提供的所有静态文件。
接下来,你需要为你的img标签指定MEDIA_URL。你现在的写法是:
<img src=160.jpg />
而实际上,它需要像这样:
<img src=[YOUR MEDIA_URL]160.jpg />
我用的技巧很简单。在我的views.py
文件的顶部,我有以下代码:
from django.conf import settings
resp = {}
resp['MEDIA_URL'] = settings.MEDIA_URL
然后我只需将resp字典传递给我渲染的每个模板。现在我可以这样写那些img标签:
<img src={{MEDIA_URL}}160.jpg />
最棒的是,这部分代码在生产环境中也可以使用(不是正则表达式,只是MEDIA_URL的部分)。
这看起来有点问题…:
r'^galleries/(landscapes)/(?P<path>.jpg)$'
这个正则表达式只会匹配在jpg
后面有一个字符的图片名称,而不是四个字符(比如说,'160.jpg'
)。也许你想要的是…
r'^galleries/(landscapes)/(?P<path>.*jpg)$'
…?
这是一篇比较长的帖子,主要总结了我在学习Django时,为了让静态文件正常工作而了解到的所有内容(我花了一段时间才搞清楚这些不同部分是如何结合在一起的)。
要在你的开发服务器(以及后来的真实服务器)上提供静态图片,你需要做几件事情(特别注意第三和第四步):
设置 MEDIA_ROOT
MEDIA_ROOT 是一个常量,它告诉Django文件的物理路径(在你的文件系统上)。根据你的例子,MEDIA_ROOT 需要设置为 'C:/siteURL/galleries/',就像你写的那样。我们设置 MEDIA_ROOT 是因为它会在后面的步骤中用到。
设置 MEDIA_URL
MEDIA_URL 是你图片所在的“网址”。换句话说,每当你想获取一张图片时,查找的地址是以 MEDIA_URL 开头的。通常这不会以“http”开头,因为你是从自己的服务器提供服务(我的 MEDIA_URL 通常设置为 '/site_media/',意思是从根域名开始,然后到 site_media 等等)。
使用 MEDIA_URL
MEDIA_URL 不是凭空就能用的,你实际上需要去使用它。例如,当你写 HTML 来获取文件时,它需要看起来像这样:
<li><img src="{{MEDIA_URL}}/160.jpg" /></li>
你看我怎么告诉模板使用 MEDIA_URL 前缀吗?这最终会变成 'http://some-good-URL/galleries/160.jpg'
。
注意,要在你的模板中实际使用 MEDIA_URL,你需要在 settings.py 文件的 TEMPLATE_CONTEXT_PROCESSORS
设置中添加一行 'django.core.context_processors.media'
,如果我没记错的话。
让你的开发服务器提供静态文件
在真实环境中,你会配置像“static_media”这样的文件地址,让它们不通过Django直接提供服务。但在开发环境中,你也想通过Django来提供这些文件,所以你应该在 urls.py 文件的末尾添加这一行:
if settings.DEBUG:
# Serve static files in debug.
urlpatterns += patterns('',
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT,
'show_indexes' : True}),
)
注意,这样会处理任何以 "site_media/*" 开头的地址(这实际上就是我的 MEDIA_URL),并从我的 MEDIA_ROOT 文件夹中提供服务,这就是 MEDIA_ROOT 设置发挥作用的地方。
最后一点
让我困惑的是,这里很多东西都是为了方便。例如,MEDIA_ROOT 只在你的调试网址模式中使用,用来告诉Django从哪里加载。而 MEDIA_URL 只是为了鼓励你不要在所有 HTML 文件中写绝对网址,因为如果你决定把文件移动到不同的服务器,你就得手动更改所有的链接(而不是只改 MEDIA_URL 常量)。
当然,这些都不是必须的:你可以把调试网址模式硬编码成自己的文件夹,确保静态文件确实是从网址提供的(通过在浏览器中访问它),然后手动把不使用 MEDIA_URL 设置的代码写入 HTML 文件,以确保一切正常工作。