在Django中访问“媒体”文件

78

我很想喜欢Django,但是在开发环境中处理静态和媒体文件的问题让我感到非常困扰。请帮我解决这个问题。

我正在我的开发机器上工作。在我的项目目录根目录下有一个名为media的文件夹。

settings.py文件中,我有:MEDIA_ROOT = ''MEDIA_URL = '/media/'

urls.py文件中,我有:

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

但是我唯一能获取媒体文件的方式是通过引用 /media/media/,例如 <img src="/media/media/image.png" />

我期望(并希望)
<img src="/media/image.png" />

有人可以告诉我这里发生了什么,并为设置媒体文件处理提供一个简单的教程吗?

非常感谢。


@Timmy O'Mahony - 谢谢!非常棒的文章,讲得很清楚。但它还留下了几个问题:

(1) 我必须使用/media//static/,而不是media/static/作为MEDIA_URLSTATIC_URL - 我错过了什么吗?

(2) 如果collectstatic损坏了/static/,那么您在哪里放置站点级别的CSS,例如站点的CSS文件?显然不能放在/static/中。

(3) 我将它们放在项目根目录下的' _ '目录中,并将STATICFILES_DIRS设置为指向它 - 尽管有urlpatterns指令,似乎这就是开发服务器获取其静态文件的地方。如果那样是错误的,您应该在开发过程中将站点级别的CSS放在哪里,并且在修改它们时collectstatic的工作流程是什么 - 每次编辑后都必须在一个地方进行编辑,然后在另一个地方收集它们吗?

9个回答

186

文件夹设置:

您的项目根目录应该类似于:

/app1
/app2
/media
/static
/templates
urls.py
settings.py
manage.py

“media”文件夹应该存储像图片、下载文件和其他可能在网站正常使用时上传的材料(即开发完成后)。

“static”文件夹应该存储与网站开发相关的所有CSS/JS文件和其他材料。


Settings.py:

MEDIA_ROOT是指上面提到的static文件夹的服务器绝对路径。这意味着它应该类似于:

MEDIA_ROOT = "/User/Bob/Sites/MySite/Project_root/media/"

MEDIA_URL是相对于浏览器的URL,当您在查看网站时,您应该从其中访问您的媒体文件。它应该是(通常情况下)

MEDIA_URL = "media/"

这意味着所有材料都可以在 http://example.com/media/ 查看。

同样,STATIC_ROOT 应该类似于

STATIC_ROOT = "/User/Bob/Sites/MySite/Project_root/static/"

STATIC_URL

STATIC_URL = "static/" 

文件服务:

现在,您已经告诉了Django这些文件应该放在哪里,并且正确指定了访问它们的URL,您需要正确地为所有请求提供文件服务。

通常,在生产环境中,您希望Web服务器负责提供静态文件和媒体文件。

不过,在开发时,您可以让Django开发服务器为您提供文件服务。

为此,您需要告诉它将所有请求路由到 http://example.com/media 到您的MEDIA_ROOT,将所有请求路由到 http://example.com/static 到您的STATIC_ROOT。

为此,在URLS.py中添加一些URL,就像您所做的那样:

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

额外内容:

如果您有多个应用,每个应用都有自己的CSS和JS文件,您可能不想将它们全部放入一个单独的/static/文件夹中。将它们放入所属应用程序的子文件夹中可能会更有用:

/app1/static/ # Specific static folder
/app2/static/
/media/
/static/ # Root static folder

现在,你的Web服务器/开发服务器只会在你指定的静态文件夹(即根静态文件夹)中寻找静态文件,所以你需要收集所有子文件夹中的文件并将它们复制到根静态文件夹中。你可以手动完成这个过程,但是Django提供了一个命令来为你完成这个任务(这就是静态应用程序的全部目的)。

./manage collectstatic

3
谢谢,我完全忘记了开发服务器的“静态服务”,一直在想为什么我的文件没有被提供服务。 如果可以的话,我会给你的帖子投很多赞的 ;) - Martin
9
我会尽力为您翻译这段内容:"I've tidied this answer up and turned it into a blog post" 的意思是:“我整理了这个回答并将其转化为博客文章。” - Timmy O'Mahony
很棒的回答和帖子。不过,你可能想在博客文章中添加媒体上下文处理器的显式添加,就像这个答案所提到的那样。否则,就像我吃了亏一样,<img src="{{ MEDIA_URL }}{{ evt_pic }}">在模板中不会被定义。从1.8+开始,它没有被显式添加。 - John C
1
说到需要media context_processor,我刚刚在阅读同样问题的其他答案时发现,有趣的是,ImageFields也提供了一个URL,因此实际上不需要context_processor和MEDIA_URL:src="{{artist.artist_image.url}} - John C
这篇博客文章或许是我迄今为止看过的关于Django静态文件最全面和易懂的写作。你是否也想在博客文章上开启评论以展开讨论? - Anupam
Django引入了一种更简洁的方法来实现这个:https://dev59.com/QHE95IYBdhLWcg3wmvKh#38446584 - Zags

33

你为什么将MEDIA_ROOT设置为空?它需要是你媒体目录的路径。如你所说,因为你的媒体文件位于名为media的子目录中,所以你应该将其放在MEDIA_ROOT中。


1
具体而言,应该是 MEDIA_ROOT = "media/" - melinath
7
为避免问题,我更喜欢使用绝对路径。在我的settings.py中,我使用一个小包装器来实现:import os.pathABSOLUTE_PATH = lambda x: os.path.join(os.path.abspath(os.path.dirname(__file__)), x)MEDIA_ROOT = ABSOLUTE_PATH('media/') - fijter

18

我按照Timmy的步骤操作,但是出现了一个错误:没有找到模块名django.views。当我在我的虚拟环境中使用import django.views时一切正常,也就是说没有库的导入问题。

然而,在我的主urls文件中遵循以下步骤,我成功解决了这个问题。

from django.conf.urls.static import  static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

https://docs.djangoproject.com/zh-hans/3.2/howto/static-files/


9
我也遇到了同样的问题,所以我添加了这些行。
from django.conf.urls import url, include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    url(r'', include('blog.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^cadmin/', include('cadmin.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

在Django项目配置目录下的urls.py文件中。更多信息请参见:https://overiq.com/django/1.10/handling-media-files-in-django/

4
在您的settings.py中,请确保将以下内容添加到TEMPLATE_CONTEXT_PROCESSORS中:

django.core.context_processors.media

否则,当您在模板中使用MEDIA_ROOT时,它将无法正常工作。

1
至少在Django 1.9.4中,这是不需要的。 - Darshan Chaudhary

3
我正在使用Django 1.10版本,并且我的媒体文件夹名为'uploads'。这是我在settings.py中的配置:
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
MEDIA_URL = '/uploads/'

在模板中,我将我的MEDIA_URL名称放在object.name之前,而不是像这样的object.url:
    <img src="uploads/{{ imagen_identificativa.name }} " alt="{{imagen_identificativa}}">

这对我有用。 希望能帮助你。


2

对于Django 3版本,我使用了以下内容:

from django.conf import settings
from django.urls import re_path
from django.views.static import serve

# ... the rest of your URLconf goes here ...

if settings.DEBUG:
    urlpatterns += [
        re_path(r'^media/(?P<path>.*)$', serve, {
            'document_root': settings.MEDIA_ROOT,
        }),
    ]

我的 settings.py

BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
STATIC_URL = '/static/'

这里有一个文档链接 https://docs.djangoproject.com/en/3.1/ref/views/ 如果您正在使用Django REST和一些开发服务器,请不要忘记更新您的开发代理设置,将/media重定向到Django后端。


1

这里有另一种选择:

在“settings.py”内设置媒体配置,类似于以下内容:

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

假设我有一个名为“person”的模态框,其中包含以下图像字段:
class Person(models.Model):
    name = models.CharField(max_length = 30)
    photo = models.ImageField(upload_to = 'photos')

现在,我们所提到的upload_to路径位于MEDIA_ROOT文件夹内。在我的情况下,将创建一个媒体文件夹,其中包含照片文件夹,我们的媒体将被转储在此处。
因此,在我的模板中,我会这样做:
<img src="{{ person.photo.url}} />

简而言之,你有一个字段,请像这样使用它:

src ={{ object.field.url}}

希望这能帮助到你!编程愉快!

0

我花了半天时间寻找解决方案。最终的关键是使用src = {{ object.field.url }}。 一切似乎都设置正确了。我使用管理员功能在根目录下创建了文件夹 - media\images\aaa.jpg

我的问题如下:

setting.py

MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media"

urls.py

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

models.py

image = models.ImageField(null=True,blank=True,upload_to="images/")

HTML文件

<img src={{quiz.image}} alt="no image found">

将上述内容更改为

<img src={{quiz.image.url}} alt="no image found">

显示图片!


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