能上传Django媒体,但无法检索

1 投票
2 回答
3200 浏览
提问于 2025-04-17 21:48

正如标题所说,我现在很困惑,因为我可以通过网站上传文件到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 个回答

1

根据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)

第二行的配置就足够了..

2

这个问题是通过打印配置参数来找出来的,也就是:

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 了。

撰写回答