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

最近,我的大学同学和他的几个前同事在筹备开公司,准备合伙创业了,要我帮他们做一个网站,我选择了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中配置才能提供服务。

排查步骤

  1. 配置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')
  1. 在模型中定义ImageField
    在模型中,我们需要使用ImageField或FileField来处理图片上传,并且可以自定义upload_to选项来指定图片的存储路径。例如:
from django.db import models
from django.conf import settings

class Image(models.Model):
    title = models.CharField(max_length=100)
    # 如果按照前面的MEDIA_ROOT配置,用户上传的图片将存放到{BASE_DIR}/media/images/目录下
    image = models.ImageField(upload_to='images/')
  1. 处理文件上传的视图函数
    在视图函数中,我们需要确保在处理表单数据时包含了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模块已经提供上传文件的功能,开发者根本不需要编写处理上传的代码。

  1. URL配置
    在项目的urls.py文件中,我们需要包含一个URL模式来处理媒体文件的请求。这也是不同于静态文件的地方,在开发环境中,Django的runserver命令会自动处理静态文件的请求。它会查找STATICFILES_DIRS和各个应用下的static目录,并直接提供这些静态文件。
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    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指定的目录中。

  1. 在模板中引用图片
    在模板中,我们需要使用模型实例的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页;

图片

加微信即可免费领取下面的自动化测试资料和一份软件测试面试宝典

图片

图片

  • 21
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值