如何在本地Django环境中提供媒体文件?

18

我可以通过管理页面上传图片,但是当我访问由Django生成的URL时,无法找到该图片。(404错误) 这些文件正在上传到文件夹:

project_root/media/eventbanner/1/

我已经尝试了多种解决方案,但似乎没有一种适用于我的情况。Django 1.10正在Ubuntu 16.04上本地运行。

我得到的URL是:

http://localhost:8000/media/eventbanner/1/banner_image.jpg

媒体根文件夹位于:

/home/username/xxx/xxx/project_name/media

HTML文件中的代码:

<div class="banner-image">
  <img src="{{ event.eventbanner.banner_image.url }}"/>
</div>

url.py代码:

from django.conf.urls import url, include
from django.contrib import admin
from . import views
from django.conf import settings
from django.conf.urls.static import static

app_name = 'events'

urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^details/(?P<event_id>[0-9]+)/$', views.details, name='details'),
url(r'^details/(?P<event_id>[0-9]+)/addcomment/$', views.add_comment, name='add_comment'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

设置.py

STATIC_URL = '/static/'
STATICFILES_DIRS =[os.path.join(BASE_DIR, 'static'),]

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

模型.py

def validate_only_one_instance(obj):
    model = obj.__class__
    if (model.objects.count() > 0 and obj.id != model.objects.get().id):
        raise ValidationError("Can only create 1 %s instance" % model.__name__)

class EventBanner(models.Model):
    event = models.OneToOneField(Event, unique=True)
    banner_image = models.ImageField(upload_to=get_image_path, blank=True, null=True)

    def clean(self):
        validate_only_one_instance(self)

请注意,使用Django 2.0+版本使此过程变得更加简单:https://docs.djangoproject.com/en/2.1/ref/urls/#static - Nielk
2个回答

27
这里的真正问题在于此URL http://localhost:8000/media/eventbanner/1/banner_image.jpg 和磁盘上此位置/home/username/xxx/xxx/project_name/media之间没有关联。
在生产应用中,您将拥有一个Web服务器,用于存储 Media 内容,服务URL将是MEDIA_ROOT,您需要将 ImageField.url 附加到该值以获取有效的图像路径。
您需要在此处设置Web服务器以供媒体图像使用。虽然一开始听起来很麻烦,但Django提供了一个快捷方式... 在开发中提供文件 您需要进行一些工作,以便本地提供媒体文件。这需要对urls.py进行一些更改...
from django.conf import settings
from django.views.static import serve

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

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

这使用了views.serve部分,应仅在DEBUG模式下使用。它覆盖媒体文件的路径(Django术语为用户上传的内容,例如ImageField)。这将通过serve视图重定向这些请求。据我所知,这是一个小型Web服务器,将这些请求路由映射到磁盘上的位置,并允许通过HTTP URL访问这些位置。


9

自Django 1.8起,有一个帮助函数static()将为您设置并确保它仅在调试模式下运行。

您的urls.py应该如下所示:

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

...只需要简单地引用文档。

确保您的MEDIA_URL设置为相对路径,例如/media/,并且您的MEDIA_ROOT是绝对文件系统路径,例如/home/foo/project/media


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