本文核心在于# 1.自己动手:前端批量上传excel到数据库
1.自己动手:前端批量上传excel到数据库
思路:利用views.py来批量实例化model,然后循环读取openpyxl来获取表单数据,并保存在实例化后的model中。无需额外建立upload_models。
#models.py
class Employee(models.Model):
eid = models.CharField(max_length=200,default='1',unique=True)
name = models.CharField(max_length=200,null=True)
dept_code = models.CharField(max_length=200,null=True)
GENDER_CHOICES = (
(u'Male', u'Male'),
(u'Female', u'Female'),
)
gender = models.CharField(max_length=200,choices=GENDER_CHOICES,null=True)
on_board = models.BooleanField(null=True)
Range_CHOICES = (
(u'R1', u'R1'),
(u'R2', u'R2'),
(u'R3', u'R3'),
(u'R4', u'R4'),
)
Range = models.CharField(max_length=200,choices=Range_CHOICES,null=True)
def __str__(self):
return self.name
#forms.py
#Employee批量上传功能
class UploadEmployeeForm(forms.Form):
uploadfile = forms.FileField()
name = forms.CharField(max_length=50)
#views.py
# 批量上传employee
def upload_employee(request):
if request.method == "POST": #验证POST
uf = UploadEmployeeForm(request.POST,request.FILES) #.post是获取post返回字段,.FILES是获取返回的文件
print(uf)
print(request.FILES['uploadfile'])
print('-----------')
if uf.is_valid(): #判断前台返回的表单是否为有效的类型
wb = load_workbook(filename=request.FILES['uploadfile'])
print(wb)
ws = wb.get_sheet_names()
ws = wb.get_sheet_by_name(ws[0])
max_row = ws.max_row
for row in range(2,max_row+1):
#获取表单元素
eid = ws.cell(row=row,column=1).value
name = ws.cell(row=row,column=2).value
dept_code = ws.cell(row=row,column=3).value
gender = ws.cell(row=row,column=4).value
on_board = ws.cell(row=row,column=5).value
Range = ws.cell(row=row,column=6).value
# 写入数据库
my_upload_employee = Employee()
my_upload_employee.eid = eid
my_upload_employee.name = name
my_upload_employee.dept_code = dept_code
my_upload_employee.gender = gender
my_upload_employee.on_board = on_board
my_upload_employee.Range = Range
my_upload_employee.save()
return HttpResponse('upload ok!')
else:
uf = UploadEmployeeForm()
return render(request,'myclass/upload_employee.html',{'uf':uf})
#urls.py
urlpatterns = [
''''''
path('upload_employee/',views.upload_employee,name='upload_employee'),
''''''
]
#upload_employee.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload_employee</title>
</head>
<body>
<form enctype="multipart/form-data" action="" method="POST">
{% csrf_token %}
{{uf.as_p}}
<input type="submit" value="upload"/>
</form>
</body>
</html>
#以下是成功的截图
2.他山之石:前端上传/下载文件到数据库
#models.py
from django.db import models
class newfile(models.Model):
username = models.CharField(max_length = 30)
headImg = models.FileField(upload_to= './upload/')
headImg2 = models.FileField(upload_to='./upload/')
#所以是用upload_to来指定文件存放的前缀路径
def __str__(self):
return self.username
#views.py
from django import forms
from django.http import HttpResponse, FileResponse
from django.shortcuts import render_to_response, render
from django.utils.http import urlquote
from onload.models import newfile
#建立Django表单,也可以在app下新建forms.py来引入
class UserForm(forms.Form):
username = forms.CharField() #字符串
headImg = forms.FileField() #文件类型
headImg2 = forms.FileField()
def register(request):
if request.method == "POST": #验证POST
uf = UserForm(request.POST,request.FILES) #.post是获取post返回字段,.FILES是获取返回的文件
if uf.is_valid(): #判断前台返回的表单是否为有效的类型
#获取表单元素
username = uf.cleaned_data['username']
headImg = uf.cleaned_data['headImg']
headImg2 = uf.cleaned_data['headImg2']
# 写入数据库
user = newfile()
user.username = username
user.headImg = headImg
user.headImg2 = headImg2
user.save()
return HttpResponse('upload ok!')
else:
uf = UserForm()
return render_to_response('register.html',{'uf':uf})
#下载页面导航
def down(request):
mail = newfile.objects.get(id=1) #此处仅做第一条数据下载,如有需要,自行修改
return render(request,'downland.html',{'i': mail})
#下载文件函数,根据down页面id自动返回id编号进行下载
def file_Download1(request,id):
ts = newfile.objects.get(id=id).headImg
tk = "F:/fileload/"+ str(ts) #此处为upload地址+数据库存的路径,可根据实际情况修改
file = open(tk, 'rb')
response = FileResponse(file)
response['Content-Type']='application/octet-stream'
response['Content-Disposition']='attachment;filename="%s"' % (urlquote(tk)) #urlquote为中文转换,防止中文名文件下载名错误
return response
def file_Download2(request,id):
ts = newfile.objects.get(id=id).headImg2
tk = "F:/fileload/"+ str(ts) #此处为upload地址+数据库存的路径,可根据实际情况修改
file = open(tk, 'rb')
response = FileResponse(file)
response['Content-Type']='application/octet-stream'
response['Content-Disposition']='attachment;filename="%s"' % (urlquote(tk)) #urlquote为中文转换,防止中文名文件下载名错误
return response
#urls.py
from django.contrib import admin
from django.urls import path,include
from myclass import views
urlpatterns = [
.....
path('app/',views.register),
path('down/',views.down),
url(r'^np1/(\d+)/$', views.file_Download1, name='file_Download1'),
url(r'^np2/(\d+)/$', views.file_Download2, name='file_Download2'),
......
]
#register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>register</h1>
<form action="" method="post" enctype="multipart/form-data">
{{uf.as_p}}
<input type="submit" value="ok">
</form>
</body>
</html>
#downland.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
username:{{ i.username }}<br>
附 件1:<a href="{% url 'file_Download1' i.id %}">{{ i.headImg }}</a><br>
附 件2:<a href="{% url 'file_Download2' i.id %}">{{ i.headImg2 }}</a><br>
</body>
</html>
3.自己动手:前端上传/下载文件到数据库
错误1:没有在urls中填写完路由。
- 错误的urls.py
urlpatterns = [
path('down/',views.down,name='down'),
]
- 错误的提示
- 正确的urls.py
urlpatterns = [
path('down/',views.down,name='down'),
path('file_Download1/<int:id>/',views.file_Download1,name='file_Download1'),
path('file_Download2/<int:id>/',views.file_Download2,name='file_Download2'),
]
错误2:带参数的url没有填对。
- 错误的urls.py
urlpatterns = [
path('file_Download1/(\d+)/',views.file_Download1,name='file_Download1'),
path('file_Download2/(\d+)/',views.file_Download2,name='file_Download2')
]
- 错误的提示
- 正确的urls.py
urlpatterns = [
path('down/',views.down,name='down'),
path('file_Download1/<int:id>/',views.file_Download1,name='file_Download1'),
path('file_Download2/<int:id>/',views.file_Download2,name='file_Download2'),
]
错误3:点击附件下载,显示错误
解法请见连接
#错误前的显示
#错误的提示
#正确的改法
views.py添加from django.utils.http import urlquote
from django.utils.http import urlquote
#正确的显示下载
最终正确的代码
#views.py
# 登记用户上传的文件
def register2(request):
if request.method == "POST": #验证POST
uf = UserForm2(request.POST,request.FILES) #.post是获取post返回字段,.FILES是获取返回的文件
if uf.is_valid(): #判断前台返回的表单是否为有效的类型
#获取表单元素
username = uf.cleaned_data['username']
headImg = uf.cleaned_data['headImg']
headImg2 = uf.cleaned_data['headImg2']
# 写入数据库
user = newfile()
user.username = username
user.headImg = headImg
user.headImg2 = headImg2
user.save()
return HttpResponse('upload ok!')
else:
uf = UserForm2()
return render(request,'myclass/register2.html',{'uf':uf})
#下载页面导航
def down(request):
mail = newfile.objects.get(id=1) #此处仅做第一条数据下载,如有需要,自行修改
return render(request,'myclass/downland.html',{'i': mail})
#下载文件函数,根据down页面id自动返回id编号进行下载
def file_Download1(request,id):
ts = newfile.objects.get(id=id).headImg
tk = os.path.join(BASE_DIR,str(ts)) #此处为upload地址+数据库存的路径,可根据实际情况修改
file = open(tk, 'rb')
response = FileResponse(file)
response['Content-Type']='application/octet-stream'
response['Content-Disposition']='attachment;filename="%s"' % (urlquote(tk)) #urlquote为中文转换,防止中文名文件下载名错误
return response
def file_Download2(request,id):
ts = newfile.objects.get(id=id).headImg2
tk = os.path.join(BASE_DIR,str(ts)) #此处为upload地址+数据库存的路径,可根据实际情况修改
file = open(tk, 'rb')
response = FileResponse(file)
response['Content-Type']='application/octet-stream'
response['Content-Disposition']='attachment;filename="%s"' % (urlquote(tk)) #urlquote为中文转换,防止中文名文件下载名错误
return response
#models.py
# 前端上传文件到数据库的试验
class newfile(models.Model):
username = models.CharField(max_length = 30)
headImg = models.FileField(upload_to= './upload/')
headImg2 = models.FileField(upload_to='./upload/')
#所以是用upload_to来指定文件存放的前缀路径
def __str__(self):
return self.username
#forms.py
#建立Django上传表单
class UserForm2(forms.Form):
username = forms.CharField() #字符串
headImg = forms.FileField() #文件类型
headImg2 = forms.FileField()
#urls.py
urlpatterns = [
path('register2/',views.register2,name='register2'),
path('down/',views.down,name='down'),
path('file_Download1/<int:id>/',views.file_Download1,name='file_Download1'),
path('file_Download2/<int:id>/',views.file_Download2,name='file_Download2'),
]