实战Django:轻松解决上传图片无法显示的问题

科技一点鑫得 2024-03-07 13:40:57

最近,我的大学同学和他的几个前同事在筹备开公司,准备合伙创业了,要我帮他们做一个网站,我选择了Django这个框架来开发,因为相对其他的框架我对它更熟悉,Django也是一款快速开发网站的优秀框架,Pinterest、纽约时报等不少知名网站也都使用了Django框架。

在使用Django进行Web开发时,上传和显示图片是一个非常常见的需求。然而,有时我们可能会遇到图片上传成功后无法在前端正确显示的问题。以下是一个我实际遇到的解决案例,我将通过这个案例来介绍如何正确地在Django中处理上传图片的显示问题。

问题描述

在我的Django项目中,有多个模型定义了Image类型的字段,如果企业logo、产品图片等,管理员可以在admin后台上传公司logo、产品图片等,上传的过程一切正常,已经确认图片已经出现在MEDIA_ROOT指定的目录中,但是点击上传后的图片链接却返回Page not found。

经过一番排查和验证,发现Django开发服务器(python manage.py runserver)默认不会对上传文件提供web服务,还需要在urls.py中配置才能提供服务。

排查步骤配置MEDIA_ROOT和MEDIA_URL:Django中除了有MEDIA_URL之外,还有个STATIC_URL,分别对应用户上传文件和静态文件,这里有必要事先对静态文件和上传文件进行说明,Django针对静态文件和上传文件是分开处理的。静态文件是指在开发过程中创建的、不会随用户交互而改变的文件,如CSS样式表、JavaScript文件、图片、字体文件等。上传文件是由网站用户生成并上传到服务器的文件,如用户头像、文档、媒体内容等。这些文件是动态生成的,与用户的交互直接相关,会随着用户的行为而变化。

首先,我们需要确保在settings.py中正确配置了MEDIA_ROOT和MEDIA_URL,其中MEDIA_ROOT定义了服务器上的一个绝对路径,这个路径是用来存储用户上传的所有媒体文件的,而MEDIA_URL定义了你的媒体文件在Web浏览器中的URL前缀,当你在网页上显示用户上传的图片或其他文件时,你需要使用这个URL前缀来构建文件的完整URL。

下面的配置只是常见的参考配置,其中MEDIA_URL中的media并不要求必须和MEDIA_ROOT中的media相同。

MEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR,'media')在模型中定义ImageField:在模型中,我们需要使用ImageField或FileField来处理图片上传,并且可以自定义upload_to选项来指定图片的存储路径。例如:from django.db import modelsfrom django.conf import settingsclass Image(models.Model): title = models.CharField(max_length=100) # 如果按照前面的MEDIA_ROOT配置,用户上传的图片将存放到{BASE_DIR}/media/images/目录下 image = models.ImageField(upload_to='images/')处理文件上传的视图函数:在视图函数中,我们需要确保在处理表单数据时包含了request.FILES,例如:def upload_image(request): if request.method == 'POST': form = ImageUploadForm(request.POST, request.FILES) if form.is_valid(): image = form.save(commit=False) # 进行其他必要的操作,如保存到数据库等 image.save() return redirect('image_detail', pk=image.pk) else: form = ImageUploadForm() return render(request, 'upload.html', {'form': form})

如果只需要在管理后台提供上传文件的能力,则Django默认的admin模块已经提供上传文件的功能,开发者根本不需要编写处理上传的代码。

URL配置:在项目的urls.py文件中,我们需要包含一个URL模式来处理媒体文件的请求。这也是不同于静态文件的地方,在开发环境中,Django的runserver命令会自动处理静态文件的请求。它会查找STATICFILES_DIRS和各个应用下的static目录,并直接提供这些静态文件。from django.conf import settingsfrom django.conf.urls.static import staticurlpatterns = [ path('admin/', admin.site.urls), path("", include("app.urls")),]# 开发服务器模式下配置上传文件web请求if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

不过这里需要特别提醒的是,无论是上传文件还是静态文件,生产环境部署都强烈不推荐直接使用Django的runserver命令,而是使用产品级的服务如nginx来为静态文件和用户上传的文件提供访问服务。

对于静态文件,建议settings.py文件中配置STATIC_ROOT,指定一个目录用于收集所有应用下的static文件,可以借助python manage.py collectstatic命令,这会将所有应用和项目的静态文件收集到STATIC_ROOT指定的目录中。

在模板中引用图片:在模板中,我们需要使用模型实例的image_field.url属性来构建图片的URL。例如:<!-- {{ image.image.url 分别对应模型对象、image字段、url属性 }} --><img src="{{ image.image.url }}">

经过以上步骤的排查和调整,最终成功解决了Django上传图片无法显示的问题,我遇到的问题是在于URL配置中没有添加处理媒体文件的请求。关键在于正确配置MEDIA_ROOT和MEDIA_URL,处理文件上传的表单和视图函数,以及在模板中正确引用图片的URL。希望这个案例能帮助你在遇到类似问题时找到解决方案。

参考文献

[1] 《Django 4 By Example》Build powerful and reliable Python web applications from scratch,Antonio Melé,346页;

0 阅读:0

科技一点鑫得

简介:感谢大家的关注