前言
本教程中,我将会使用Django和Vue创建一个支持多文件上传的文件上传器。您可以在单个文件和多个文件上传之间选择在应用中进行上传操作。因此在这里您可以在本教程中我们将要构建的内容:
在完成上传操作以后,您可以在项目文件下找到上传的文件,而且它们按照年月日进行了分类:
同名文字的处理:Django会对同名文件进行重命名处理,非常方便
这看上去很不错。现在让我们开始编码吧!
Django部分
构建Django项目
(可选)创建项目虚拟环境
其实使用本机的全局环境也是可以的,看个人喜好。
python -m venv env
激活虚拟环境
envScriptsactivate
退出虚拟环境命令--deactivate
安装Django及其他项目依赖
pip install django,django-cors-headers
创建Django app
python manage.py startapp document
完成上述操作后,项目目录如下:
配置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后端需要解决跨域问题和csrf跨站请求保护,跨域可以通过django-cors-headers
解决,而csrf跨站请求需要csrfToken
和csrfCookie
双重认证,由于笔者的水平有限,只能实现前端从后端请求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