使用Django+Vue编写一个文件上传器

2023年 7月 14日 68.6k 0

前言

本教程中,我将会使用Django和Vue创建一个支持多文件上传的文件上传器。您可以在单个文件和多个文件上传之间选择在应用中进行上传操作。因此在这里您可以在本教程中我们将要构建的内容:

django-vue-uploader.gif

在完成上传操作以后,您可以在项目文件下找到上传的文件,而且它们按照年月日进行了分类:

同名文字的处理:Django会对同名文件进行重命名处理,非常方便

image.png

这看上去很不错。现在让我们开始编码吧!

Django部分

构建Django项目

(可选)创建项目虚拟环境

其实使用本机的全局环境也是可以的,看个人喜好。

python -m venv env

激活虚拟环境

envScriptsactivate

退出虚拟环境命令--deactivate

安装Django及其他项目依赖

pip install django,django-cors-headers

image.png

创建Django app

python manage.py startapp document

完成上述操作后,项目目录如下:

image.png

配置settings.py

添加document应用到INSTALL_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'document'
]

配置媒体路径,指定上传文件的存放位置

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

构建document应用

创建模型(models.py)

进入document文件夹,为文件上传创建数据库模型

from django.db import models


class Document(models.Model):
    document = models.FileField(upload_to='uploads/%Y/%m/%d')

    def __str__(self):
        return str(self.pk)

upload_to文件存放位置:基于MEDIA_ROOT的起始路径。这里的uploads/指文件将要存放在media目录下新建的uploads文件夹,可往下递推。

完成数据库模型的设置后,转到终端将设置写入到数据库

python manage.py makemigrations
python manage.py migrate

创建表单(forms.py)

我们可以新建一个新的表单用于提交上传文件到数据库

from django import forms

from .models import Document

class UploadForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ('document', )

    def save_multiple(self, documents):
        for file in documents:
            document = Document(document=file)
            document.save()

编写接口(views.py)

编写views.py,添加multiply_upload接口,通过JsonResponse返回上传状态

from django.middleware.csrf import get_token
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

from .forms import UploadForm

@csrf_exempt
def multiply_upload(request):
    if request.FILES:
        form = UploadForm(request.FILES)
        if form.is_valid():
            documents = request.FILES.getlist('document')
            form.save_multiple(documents)

    return JsonResponse({'message': 'success'})

添加路由(urls.py)

在app目录下添加视图路由

from django.urls import path
from . import views

urlpatterns = [
    path('multiply-upload/', views.multiply_upload, name='multiply_upload')
]

在core目录下添加api路由

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

# 完整路径地址示例:http://example.com/api/multiply-upload/
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('document.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

添加 static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 是为了能够在服务端地址上访问media内的文件

至此,django后端构建完成,接下来编写Vue代码

Vue部分

我之前写过一篇文章就是关于使用Vue编写文件上传组件的内容,那里已经详细地把前端的大部分内容编写完毕。如果还没看的同学可以移步至这里来制作文件上传组件。

这里主要编写前后端的数据通信,使用axios发送http请求

function multipleFilesUpload() {
   const formData = new FormData()
       files.value.forEach((file) => {
          formData.append('document', file)
	  })
	  axios
		.post('http://127.0.0.1:8000/api/multiply-upload/', formData, {
		     headers: {
			  'Content-Type': 'multipart/form-data',
		     },
		})
		.then((res) => console.log(res.data.message))
		.catch((error) => {
		     console.log('error :>> ', error)
		})
	  files.value = ''
}

添加一个按钮以发送上传请求

   
			上传
   

处理跨域问题

通过django-cors-headers处理跨域请求(settings.py)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders', 
    'document'
]

添加中间件corsheaders.middleware.CorsMiddleware

注意:跨域中间件要添加在django.middleware.common.CommonMiddleware之前

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

配置跨域规则

CORS_ALLOWED_ORIGINS = ["http://localhost:5173"]  # 前端地址
CORS_ALLOW_METHODS = [
    "DELETE",
    "GET",
    "OPTIONS",
    "PATCH",
    "POST",
    "PUT",
]
CORS_ALLOW_HEADERS = [
    "accept",
    "accept-encoding",
    "authorization",
    "content-type",
    "dnt",
    "origin",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
]

设置完成后,可以启动项目验证功能是否正常运行。

启动项目

前端

在前端工程文件目录下运行:

npm run dev

github仓库的项目使用的是yarn dev,使用yarn还是npm看个人喜好

后端

先迁移数据库(克隆项目的情况下)

python manage.py makemigrations
python manage.py migrate

启动项目

python manage.py runserver

测试效果

django-vue-uploader.gif

这看上去很酷,但是很多方面需要扩展,比如进度条,显示上传状态...不过最基本的功能已经实现,后面同学们可以根据自己的需要扩展功能。

写在最后

这个后端示例并不是一个很好的示范,前后端分离模式下前端发送请求至django后端需要解决跨域问题和csrf跨站请求保护,跨域可以通过django-cors-headers解决,而csrf跨站请求需要csrfTokencsrfCookie双重认证,由于笔者的水平有限,只能实现前端从后端请求csrftoken然后将其添加到请求头中,但是没有cookie仍是不能实现上传。最后在后端通过django提供的装饰器,为特定的视图加上装饰器进行csrf的豁免。

#FBV:直接在函数上方加装饰器  @csrf_exempt  即可不验证csrf

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def multiply_upload(request):
      # 处理逻辑

如果有对这块熟悉的朋友可以在评论区指导一下,我先在这里感谢各位了!

后面会更新使用rest_framework实现的类视图的多文件上传接口,我个人觉得使用DRF写接口要方便得多,作为一个前端开发者,使用Django作为后端开发语言确实要得心应手一些。

再次感谢您的阅读!

源码参考:github

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论