在项目过程中,也许我们需要上传一张图片,或者需要上传一份文件,那么有什么方式既简单又有效呢,使用django该怎么做呢?
本文是自己在开发中有需要摸索出来的,使用了REST-framework如果有更好的方式,烦请留言相告,不胜感激!!
1、django的安装启动就不在赘述了
2、 在settings.py配置上传的路径
FILE_URL = "static/%Y/%m/files/" # 例如将文件放在项目目录下的static/2018/12/files/下(将在代码中做格式化)
FILE_ROOT = os.path.join(BASE_DIR, FILE_URL) # 文件目录绝对路径
2、创建好模型
用户模型也不再赘述了。可以使用自带的认证用户模型。
class File(BaseModel):
# upload_to参数是后台admin上传图片的保存位置,我们后续自己写的接口,图片也保存在这个位置
file = models.FileField(upload_to=settings.FILE_URL, verbose_name="文件选择")
name = models.CharField(max_length=200, blank=True, verbose_name="文件名称")
class Meta:
db_table = 'test_file'
verbose_name = "文件"
verbose_name_plural = verbose_name
def __str(self):
return self.name
3、迁移数据库,在项目目录下使用命令
python manage.py createsuperuser
创建好admin超级用户。(本来是无需创建的,这里只是为了做测试)
4、 在当前应用app下的admin.py注册模型
from django.contrib import admin
from .models import File
admin.site.register(File)
5、python manage.py runserver 开启django服务器,打开默认网址127.0.0.1:8000/admin,登录admin超级管理员,就可以看到
点击模型,增加文件。保存。查看数据库,会发现
超级管理员是好办,已经完成了,文件就在项目目录下的static/2018/12/files/下。
在app下的views.py写好后端接口
import os
import datetime
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import FileSerializer
from .models import File
class FileView(APIView):
def get(self, request):
"""获取指定id的文件,前端传入id"""
file_id = request.GET.get("id")
try:
file = File.objects.get(id=int(file_id)) # 查询
except Exception as e:
return Response({"file": '', 'error': 'file does not exist'})
serializer = FileSerializer(instance=file) # 返回数据的序列化器
return Response(serializer.data)
def post(self, request):
"""上传文件的接口"""
file_obj = request.FILES.get('file') # 获取前端的文件
file_uuid = request.POST.get('uuid') # uuid
file_name = file_uuid + file_obj.name # 重新组成file_name
time = datetime.datetime.now()
file_root = time.strftime(settings.FILE_ROOT) # 格式化保存路径
if os.path.exists(file_root):
pass
else:
os.makedirs(file_root) # 路径不存在就建立文件夹
file_path = os.path.join(file_root, file_name) # 文件路径
f = open(file_path, 'wb')
# 写入保存上传的文件
for chunk in file_obj.chunks():
f.write(chunk)
f.close()
file_url = time.strftime(settings.FILE_URL) + file_name
file = File.objects.create(
file=file_url,
name=file_obj.name,
)
file.save()
return Response({"status": "upload success!", "file": file_url}) # 成功返回状态及文件的路径
配置好后端访问的urls
from django.urls import path
from . import views
urlpatterns = [
path(r'file/', views.FileView.as_view())
]
# 这是app下的url,项目的url请自行喜欢配置哈
补充序列化器serialisers.py:
from rest_framework import serializers
from .models import File
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields = '__all__'
6、写好前端html页面
上传文件
{# 配置后端的接口域名host.js文件内容就一行#}
{# var host = "http://127.0.0.1:8000/";#}
7. uplode_file.js
$(function(){
// 点击上传按钮触发上传事件,如果想选择好文件就上传可以使用$("#upFile").change()函数
$("#fileSubmit").click(function(){
var formData = new FormData();
var file = $("#upFile").get(0).files[0]; // 获取input选入的文件内容
var uuid = generateUUID(); // 生成uuid
formData.append('file', file); // 加入数据表单
formData.append('uuid', uuid); // 传入uuid
$.ajax({
url: 'http://127.0.0.1:8000/file/', // 后端django接口
type: "POST",
data:formData,
processData: false,
contentType: false,
success: function(data){
alert("success!");
},
error: function(e){
alert("网络错误,请稍后再试!\n")
}
})
});
// 生成唯一的uuid,上传相同的文件一样保存
function generateUUID() {
var d = new Date().getTime();
if(window.performance && typeof window.performance.now === "function"){
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid;
}
})
最后!运行django服务器,开启前端页面,选择文件,上传。
成功后会在项目目录下生成static文件夹。一层层进里面就躺着我们上传的文件啦!
打开数据库查看,file字段与我们后台admin配置的upload_to上传的一样。