能上传Django媒体,但无法检索
正如标题所说,我现在很困惑,因为我可以通过网站上传文件到MEDIA_ROOT,但当我尝试访问这些文件时却出现404错误。最让人烦恼的是,这个功能之前一直正常,现在突然出问题了。
更新:我找到了问题的关键。
如果我把这个设置改成:MEDIA_URL = '/media/'
那么Django会在这个地址提供文件:http://192.168.xxx.xxx/media/media/file.txt
如果我把这个设置改成:MEDIA_URL = '/kittens/'
那么Django会在这个地址提供文件:http://192.168.xxx.xxx/kittens/file.txt
runserver的输出:
urls.py MEDIA_URL: /media/
urls.py MEDIA_ROOT:
Settings.py MEDIA_ROOT: /home/user/kittens/
到底发生了什么?为什么会出现“嵌套”的媒体网址路径?django.conf.settings.MEDIA_ROOT
是空的,而mysite.settings.MEDIA_ROOT
却不是?
urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
print 'urls.py MEDIA_URL: %s' % (settings.MEDIA_URL)
print 'urls.py MEDIA_ROOT: %s' % (settings.MEDIA_ROOT)
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = '/home/user/kittens/'
print 'Settings.py MEDIA_ROOT: %s' % (MEDIA_ROOT)
磁盘上的文件
drwxr-xr-x 0 user user 0 Mar 11 11:00 kittens/
-rwxr-xr-x 0 user user 22561 Oct 5 19:17 kittens/file.txt*
在浏览器中
Page not found (404)
Request Method: GET
Request URL: http://192.168.../media/file.txt
"file.txt" does not exist
运行命令:python manage.py runserver
[11/Mar/2014 15:00:43] "GET /media/file.txt HTTP/1.1" 404 1629
运行命令:python manage.py shell
IPython 1.1.0 -- An enhanced Interactive Python.
In [1]: from django.conf import settings
In [2]: settings.MEDIA_ROOT
Out[2]: 'kittens/'
In [3]: settings.MEDIA_URL
Out[3]: '/media/'
In [8]: os.path.join(settings.MEDIA_ROOT, 'file.txt')
Out[8]: 'kittens/file.txt'
In [9]: os.path.exists(os.path.join(settings.MEDIA_ROOT, 'file.txt'))
Out[9]: True
2 个回答
根据django的文档,MEDIA_ROOT必须是一个绝对路径:
MEDIA_ROOT
默认值:''(空字符串)
这是一个绝对的文件系统路径,用来存放用户上传的文件的目录。
举个例子:"/var/www/example.com/media/"
所以如果你想把媒体文件放在你的项目里,你的配置应该像这样:
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'kittens/')
或者使用一个绝对路径:
MEDIA_ROOT = /user/uploaded/files/kittens/
补充: 因为你更新了你的问题,上面的回答就不相关了。不过我发现你在配置url时,媒体路径配置了两次,这可能是个问题:
url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
第二行的配置就足够了..
这个问题是通过打印配置参数来找出来的,也就是:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = '/home/user/kittens/'
print 'Settings.py MEDIA_ROOT: %s' % (MEDIA_ROOT)
urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
print 'urls.py MEDIA_URL: %s' % (settings.MEDIA_URL)
print 'urls.py MEDIA_ROOT: %s' % (settings.MEDIA_ROOT)
python manage.py runserver
urls.py MEDIA_URL: /media/
urls.py MEDIA_ROOT:
Settings.py MEDIA_ROOT: /home/user/kittens
Validating models...
你会注意到 urls.py
中的 MEDIA_ROOT
是空的。检查 settings.py
后,我发现根网址的配置在 MEDIA_ROOT
配置之前就被调用了。所以,调整这个顺序就解决了问题。
settings.py
# Must specify MEDIA_ROOT first so urls.py picks it up via django.conf.settings
MEDIA_ROOT = '/home/user/kittens'
# Then call site root's urls.py
ROOT_URLCONF = 'mysite.urls'
我不知道这怎么导致了“嵌套”的媒体路径,但这个调整确实解决了问题。也就是说,我现在可以访问 http://192.168.xxx.xxx/media/file.txt
了。