无法在Django开发环境中处理静态图片

2 投票
3 回答
4405 浏览
提问于 2025-04-15 20:28

我看过这篇文章(还有其他几篇相关的),但还是搞不清楚怎么显示图片,除非在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 个回答

1

可以把这个看作是之前两个答案的结合,两个答案都挺不错的。首先,你的正则表达式是错误的,正如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的部分)。

5

这看起来有点问题…:

r'^galleries/(landscapes)/(?P<path>.jpg)$'

这个正则表达式只会匹配在jpg后面有一个字符的图片名称,而不是四个字符(比如说,'160.jpg')。也许你想要的是…

r'^galleries/(landscapes)/(?P<path>.*jpg)$'

…?

10

这是一篇比较长的帖子,主要总结了我在学习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 文件,以确保一切正常工作。

撰写回答