【Django+vue3】上传和显示图片

最近在学习使用django和vue3写一个前后端项目,在上传用户图片这边卡了好一会儿,网上找了好多资料,最后还是自己总结了一点经验,分享给大家。

        我在前端使用的是Element plus的el-upload组件上传图片,后端用户的头像字段采用的是ImageField类型。 ImageField是Django数据库的一种数据类型,varchar类型,通常用来保存图片的名称,而想要了解el-upload具体有哪些属性可以参考:Upload 上传 | Element Plus

        两者具体怎么用看下面的流程。

目录

一、 前端代码

二、后端代码

1. 上传图片

2. 显示上传的图片


一、 前端代码

        首先,上传头像需要用到前端的el-upload组件,如以下代码:

<!-- 这里的uploadUrl是http://127.0.0.1:8000/media/upload/uploadAvatar -->
<el-upload
    :action="uploadUrl"
    :auto-upload="true"
    :on-success="handleAvatarSuccess"
    :before-upload="beforeAvatarUpload"
 >
    <img
       v-if="imageUrl"
       :src="imageUrl"
    />
    <i v-else></i>
</el-upload>

        其中,action规定了上传头像对应的url,这是一会儿要和后端对应上的;auto-upload是自动上传;on-success是上传成功后的操作,而before-upload规定了上传前的操作,通常用来判断图片格式、大小是否满足要求。这里在el-upload里面放了一个img标签,用来显示图片,当imageUrl能从后端请求到图片时就显示图片,否则显示一个空的链接。

        下面是我在methods中规定的on-success和before-upload对应的行为:

// 上传成功后进行数据处理
handleAvatarSuccess(res) {
  // 显示上传是否成功
  if (res.code == 0) {
     this.$message.success(res.msg);
  } else {
     this.$message.error(res.msg);
  }
  // 规定新的imageUrl为 <"http://127.0.0.1:8000/media/user/"+文件名>
  this.imageUrl = "http://127.0.0.1:8000/media/user/" + res.file;
  // 更新user的photo字段值
  this.user.photo = res.file;
},

// 上传前判断图片大小是否满足要求
beforeAvatarUpload(file) {
  const isLt10M = file.size / 1024 / 1024 < 200;
  if (!isLt10M) {
     this.$message.error('上传头像图片大小不能超过 200MB!');
  }
  return isLt10M;
},

        至此,前端部分基本上编写完成。界面如下(这里我没给出css样式,大家自行解决咯):

          

二、后端代码

        后端的django需要接收到前端的请求并作出相应处理。这里要着重区分两个请求:一个是上传图片的请求,也就是el-upload中:action对应的请求;另一个是图片上传后显示图片的请求,也就是img标签中:src对应的值。接下来我们拆分成两点进行分析。

1. 上传图片

        在上传图片前,先在models.py文件下写一个user类,可以参考下面的代码:

class User(models.Model):
    username = models.CharField(max_length=30, unique=True)
    password = models.CharField(max_length=20)
    photo = models.ImageField(max_length=100, blank=True, null=True, default='')
    # 可以自己添加其他字段

        其中photo字段用的是ImageField类型(不过本人实测过,如果存储的仅仅是图片名称的话,用CharField也是完全OK的,没有影响) 

        接下来在settings.py中规定路径:

# 头像保存路径
USER_AVATAR_ROOT = os.path.join(BASE_DIR, 'static/images/user')

        USER_AVATAR_ROOT指定了头像保存的路径,即<根目录 + static/images/user> ,大家可以自行替换。

        接下来到urls.py中添加一条路径:

path("media/upload/uploadAvatar", views.saveImage),

         这个路径对应的就是el-upload中的action路径,也就是当用户在前端界面选择了一个头像时,el-upload会自动发送action规定的post请求,给后端处理,我这里规定的是"media/upload/uploadAvatar",大家可以自行替换,但要保证前后端的请求url一致。

        最后就是编写views.py中的saveImage函数,该函数用来保存图片至指定的路径,也就是实现图片上传功能:

def saveImage(request):
    response = {}
    # 获取前端发来的的file对象
    file = request.FILES.get('file')
    try:
        # 构造图片保存路径 路径为<USER_AVATAR_ROOT + 文件名>
        # USER_AVATAR_ROOT刚刚在settings.py中规定过,需要导入进来
        file_path = os.path.join(USER_AVATAR_ROOT, file.name)
        # 保存图片
        with open(file_path, 'wb+') as f:
            f.write(file.read())
            f.close()
        response['file'] = file.name # 返回新的文件名
        response['code'] = 0
        response['msg'] = "图片上传成功!"
    except:
        response['file'] = ''
        response['code'] = 1
        response['msg'] = "图片上传失败!"
    return JsonResponse(response)

         这里要注意的是,el-upload发送的post请求中带有FILES类型的文件,通过file = request.FILES.get('file')可以得到这个文件,在此基础上,file.name可以得到文件名,file.read()可以读取文件内容。

        至此,我们已经可以实现 “用户选择图片->后端接收请求->后端保存图片”这些功能。图片将会如我们规定的一样保存至指定路径,如下图:

                

2. 显示上传的图片

        但是,如果照着上面的步骤进行下去的话,大家可能发现头像并不能在前端显示出来,那是因为我们只保存了头像,而并未指定如何显示头像。这时候就要用到前端img标签中指定的路径了,刚刚我们指定的url是 <"http://127.0.0.1:8000/media/user/" + res.file>,其中res.file就是我们刚刚后端返回的新的图片名。为了与前端指定的url对应,我们也需要在后端加上对应的请求。

        我们在urls.py的urlpatterns中再加上一行:

re_path(r'^media/user(?P<path>.*)$', serve, {'document_root': settings.USER_AVATAR_ROOT}),

        这个url与普通的url不太一样,可以用来加载如图片之类的静态资源,其中media/user(?P<path>.*)与刚刚前端规定的url<"http://127.0.0.1:8000/media/user/" + res.file>相对应,而settings.USER_AVATAR_ROOT就表明,当后端接收到这个url请求后,就转而去我们指定的路径(USER_AVATAR_ROOT)中去找图片,并返回给前端。这一系列的操作都由django替我们完成,无需自己再编写views.py中的请求处理方法。

        至此,更换后的图片就能完美地显示在前端界面中了:

        


        后话:可能会有小伙伴使用“直接指定本机路径”的方法来存储和显示用户头像,结果前端会报“file不安全”之类的错误,这种粗暴的方法既不优雅,也不符合Web开发的思想。说到底,把头像集中上传到指定位置、再发送请求通过后端服务器获取头像才是正解。

        新人发帖,多多关照噢~ Wink~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值