5

Django(drf)配合 Vue Element 实现文件上传下载功能

 3 years ago
source link: http://www.starky.ltd/2021/03/13/django-drf-and-vue-element-file-upload-and-download/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Django(drf)配合 Vue Element 实现文件上传下载功能

发表于 2021-03-13

| 分类于 Python

| 0

| 阅读次数: 53

字数统计: 6.3k

|

阅读时长 ≈ 0:06

Models

编辑 models.py 代码,通过 FileField 字段记录文件信息:

from django.db import models


class FilesModel(models.Model):
file = models.FileField(upload_to='uploads/')

class Meta:
db_table = 'files_storage'
ordering = ['-id']
Serializer

这里使用 Django REST framework 实现后端 REST API,需要创建序列化器 serializers.py,内容如下:

from rest_framework import serializers
# files 是 app 的名字
from files import models


class FilesSerializer(serializers.ModelSerializer):
class Meta:
model = models.FilesModel
fields = '__all__'
Views

编辑 views.py 代码,内容如下:

from rest_framework.viewsets import ModelViewSet
from files import models, serializers


class FileViewSet(ModelViewSet):
queryset = models.FilesModel.objects.all()
serializer_class = serializers.FilesSerializer

在 files 路径下新建 urls.py 文件,填写路由配置:

from django.urls import include, path
from rest_framework import routers
from files import views

router = routers.DefaultRouter()
router.register(r'files', views.FileViewSet)

urlpatterns = [
path('', include(router.urls))
]

在项目总配置路径下(settings.py 所在的路径)编辑根路由配置文件 urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('storage/', include('files.urls'))
]
测试后端 API

运行后台服务 python manage.py runserver 0.0.0.0:8000,访问 http://xx.xx.xx.xx:8000/storage/files/,界面如下:
Django REST framework

测试上传文件,效果如下:
上传成功

前端代码(手动上传)

借助 Element UI 的 upload 组件,Vue 代码(index.vue)如下:

<template>
<div>
<el-upload
ref="upload"
drag
action="http://xx.xx.xx.xx:8000/storage/files/"
:auto-upload="false"
:on-success="onSuccess"
>
<i class="el-icon-upload" />
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
</div>
</template>

<script>

export default {
name: 'UploadDemo',
methods: {
submitUpload() {
this.$refs.upload.submit()
},
onSuccess() {
this.$message.success('上传成功')
}
}
}
</script>

其中 el-upload 组件的 action 属性用于指定后台 API 的 URI;
:auto-upload 属性用于设置是否自动上传(这里设置为 false,手动触发上传动作);
:on-success 属性用于指定上传成功后触发的方法。

submitUpload() 中的 this.$refs.upload.submit() 方法触发文件上传动作。

界面如下:
上传界面

测试文件上传:
上传成功

后台数据如下:

[
{
"file": "http://172.20.23.34:8000/storage/files/uploads/template.html",
"id": 18
},
{
"file": "http://172.20.23.34:8000/storage/files/uploads/20171215091830_55126_hSnPtZR.png",
"id": 17
}
]

文件上传的同时添加其他数据

修改数据库模型

编辑后端 models.py 文件,添加其他字段:

from django.db import models


class FilesModel(models.Model):
name = models.CharField(max_length=20, default='')
file = models.FileField(upload_to='uploads/')

class Meta:
db_table = 'files_storage'
ordering = ['-id']

数据库迁移后,重启后台 Web 服务。

后台数据如下:

[
{
"file": "http://172.20.23.34:8000/storage/files/uploads/template.html",
"id": 18,
"name": ""
},
{
"file": "http://172.20.23.34:8000/storage/files/uploads/20171215091830_55126_hSnPtZR.png",
"id": 17,
"name": ""
}
]
修改前端代码

添加其他数据的输入界面,同时将附加数据绑定到 el-upload 组件中:

<template>
<div>
<el-label>名称</el-label>
<el-input v-model="fileData.name" style="width: 20%" />
<el-upload
ref="upload"
drag
class="upload-demo"
action="http://xx.xx.xx.xx:8000/storage/files/"
:data="fileData"
:auto-upload="false"
:on-success="onSuccess"
style="padding: 30px"
>
<i class="el-icon-upload" />
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
</div>
</template>

<script>

export default {
name: 'UploadDemo',
data() {
return {
fileData: {
name: ''
}
}
},
methods: {
submitUpload() {
this.$refs.upload.submit()
},
onSuccess() {
this.$message.success('上传成功')
}
}
}
</script>

其中 el-upload 组件的 :data 属性用于指定文件上传时附加的数据(类型为 JavaScript 对象)。

文件上传测试:
文件上传(带数据)

上传完成,后台数据如下:

[
{
"file": "http://172.20.23.34:8000/storage/files/uploads/AnyDesk.exe",
"id": 19,
"name": "测试文件"
},
{
"file": "http://172.20.23.34:8000/storage/files/uploads/template.html",
"id": 18,
"name": ""
},
{
"file": "http://172.20.23.34:8000/storage/files/uploads/20171215091830_55126_hSnPtZR.png",
"id": 17,
"name": ""
}
]

修改后台视图代码(views.py),添加文件下载的 API 响应逻辑:

from rest_framework.viewsets import ModelViewSet
from files import models, serializers
from rest_framework.decorators import action
from django.http import FileResponse


class FileViewSet(ModelViewSet):
queryset = models.FilesModel.objects.all()
serializer_class = serializers.FilesSerializer

@action(methods=['get', 'post'], detail=True)
def download(self, request, pk=None, *args, **kwargs):
file_obj = self.get_object()
response = FileResponse(open(file_obj.file.path, 'rb'))
return response

此时访问 http://xx.xx.xx.xx:8000/storage/files/[id]/download/ 链接,即可直接下载上传到服务器上的文件。
下载文件

$ curl -o anydesk.exe 172.20.23.34:8000/storage/files/19/download/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3584k 100 3584k 0 0 102M 0 --:--:-- --:--:-- --:--:-- 102M

Element UI 官方文档
Django 官方文档


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK