Django的MEDIA_URL和MEDIA_ROOT

298

我正在尝试通过Django后台上传图像,然后在前端页面上或仅通过URL查看该图像。

请注意,这全部都是在我的本地机器上进行的。

我的设置如下:

MEDIA_ROOT = '/home/dan/mysite/media/'

MEDIA_URL = '/media/'

我已将upload_to参数设置为“images”,文件已正确上传到目录:

'/home/dan/mysite/media/images/myimage.png'

然而,当我尝试访问以下URL的图像时:

http://127.0.0.1:8000/media/images/myimage.png

我收到了一个404错误。

我需要为上传的媒体设置特定的URLconf模式吗?

欢迎任何建议。

谢谢。

18个回答

367

Django >= 1.7 更新说明

按照 Django 2.1 文档: 在开发期间服务于用户上传的文件

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

现在 Django 会处理确保只有在 Debug 模式下才使用 if settings.DEBUG,因此你不再需要这个判断了。


Django 版本小于等于 1.6 的原始回答:

尝试将以下代码放入你的 urls.py 中:

from django.conf import settings

# ... your normal urlpatterns here

if settings.DEBUG:
    # static files (images, css, javascript, etc.)
    urlpatterns += patterns('',
        (r'^media/(?P<path>.*)$', 'django.views.static.serve', {
        'document_root': settings.MEDIA_ROOT}))

通过这种方式,你可以在 DEBUG = True 时(本地运行时)从 Django 提供静态媒体文件,但是当你进入生产环境且 DEBUG = False 时,你可以让 Web 服务器配置提供静态媒体文件。


16
你可以在模板中使用以下代码: <img src="{{ MEDIA_URL }}images/myimage.png"/>。 - Micah Carrick
我认为在media//(?P<path>.*)$之前添加^符号并不好,因为有时候当我们在应用程序URL路径中访问媒体文件(例如http://127.0.0.1:8000/myapp/media/img/logo.png)时,这个正则表达式将无法匹配。 - Jack Zhang
我已经苦苦思索了两天,为什么我的图片返回404。这是我唯一缺失的东西,我在Django文档中找不到它。谢谢。 - tambalolo
1
如果您正在使用 Django 1.5 或更高版本,请查看下面的答案;它是更好的解决方案。 - Thane Brimhall
这个是在你的应用程序或项目的urls.py文件中吗? - user7804781
显示剩余3条评论

116
请仔细阅读官方 Django 文档,您将找到最适合的答案。
解决此问题的最佳和最简单方法如下所示。
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

2
这是在Django 1.5中新增的一个功能。 - codeVerine
在生产环境中使用Apache,这种方式可行吗? - andilabs
1
@andi - 不,这种方式在生产环境中使用是不可行的。它应该通过Apache在您的生产环境中进行配置。 - Vikas Gulati
1
在1.7版本中 https://docs.djangoproject.com/en/1.7/howto/static-files/#serving-files-uploaded-by-a-user-during-development - ErDmKo
1
这段代码没有if settings.DEV检查,但在生产环境中保留它并不会有问题,因为它会自动禁用吗? - jozxyqk
显示剩余2条评论

77

2
这是适用于Django >1.9的解决方案,谢谢。 - unixeo
19
请确保将此内容放入您的 项目(project) 的urls.py文件中,而不是您的应用程序(app)中的文件,这是我不小心犯下的错误。 - Jarno
3
1.10版本也适用于我。 - CoderGuy123
对我来说不起作用。也许在settings.py中有必要的基础设置? - Fusion

39

以下是我在 Django 2.0 中所做的。首先,在 setting.py 中设置了 MEDIA_ROOT 和 MEDIA_URL。

MEDIA_ROOT = os.path.join(BASE_DIR, 'data/') # 'data' is my media folder
MEDIA_URL = '/media/'

然后在TEMPLATE_CONTEXT_PROCESSORS中添加media context_processors以启用。
TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [],
    'APP_DIRS': True,
    'OPTIONS': {
        'context_processors': [
            #here add your context Processors
            'django.template.context_processors.media',
        ],
    },
},
]

您的媒体上下文处理器已启用,现在每个RequestContext都将包含一个变量MEDIA_URL

现在您可以在您的template_name.html中访问它。

<p><img src="{{ MEDIA_URL }}/image_001.jpeg"/></p>

2
讲解得非常好 - 这就是我的答案。关键是添加媒体上下文处理器 - David Maness
2
非常好的context_processors提示 - artu-hnrq

24

上传的媒体文件需要设置特定的URLconf模式吗?

是的。对于开发而言,只需将以下内容添加到您的URLconf即可:

if settings.DEBUG:
    urlpatterns += patterns('django.views.static',
        (r'media/(?P<path>.*)', 'serve', {'document_root': settings.MEDIA_ROOT}),
    )

然而,对于生产环境,您将希望使用Apache、lighttpd、nginx或您偏爱的Web服务器来提供媒体。


4
这句话的意思是“那是什么意思?你要如何配置服务器?” - Menachem Hornbacher
我得到了一个对“patterns”的未解决引用,那是从某个地方导入的吗? - user7804781

8
如果您使用的是 Python 3.0+,则请按照以下方式配置您的项目。
设置
STATIC_DIR = BASE_DIR / 'static'
MEDIA_DIR = BASE_DIR / 'media'
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'

主要网址

from django.conf import settings
from django.conf.urls.static import static

urlspatterns=[
........
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

6

对于 Django 1.8 及以上版本:

如果您使用的是

if settings.DEBUG:
  urlpatterns.append(url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}))

如上所述,请确保在urlpatterns = []中没有指向默认视图的“catch all” URL模式。由于.append将添加的方案放在列表的末尾,因此只有在没有前面的URL模式匹配时才会测试它。您可以通过使用类似于这样的内容来避免这种情况,在if语句之外添加“catch all” URL模式:

if settings.DEBUG:
    urlpatterns.append(url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}))

urlpatterns.append(url(r'$', 'views.home', name='home')),

6
以下是我为了使用 Django 1.10.6,为 django-publications 应用程序交付 PDF 所做的更改:

settings.py 中,使用与您相同的媒体目录定义:

MEDIA_ROOT = '/home/user/mysite/media/'

MEDIA_URL = '/media/'

根据@thisisashwanipandey提供的,项目的主urls.py

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

以下是对 @r-allela 在 settings.py 中提供答案的修改:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                # ... the rest of your context_processors goes here ...
                'django.template.context_processors.media',
            ],
         },
    },
]

5

按照上面提到的步骤进行=>3.0的调试模式

urlpatterns = [
...
]
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

还有一点让我意外的是,上述静态URL仅适用于我的主要项目urls.py文件。 我最初尝试添加到我的应用程序中,并想知道为什么看不到图像。

最后确保您设置了以下内容:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

5

在设置好所有URLconf模式后,你可能会遇到另一个问题,即变量{{ MEDIA_URL }}在你的模板中无法工作。为了解决这个问题,在你的settings.py文件中,请确保将以下内容添加到TEMPLATE_CONTEXT_PROCESSORS中:

django.core.context_processors.media

这样就可以解决问题了。


这是更好的选择,但对我来说'django.template.context_processors.media'也起作用。 - Sumit Kumar Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接