django页面导入导出,文件上传
django页面导入导出
导出的业务比较通用,广泛,需要开发效率,可以使用 django_import_export
导入,业务不常用,但需要定制化,错误消息要详细,用django_import_export导入,一般用在后台或开发人员自己转移数据。 但提供给前台用户,
还需要选择可定制的,我选择django_tablib插件。
一、导出
可定制:改变列名,增加model不存在的列名,foreign关联提取等等
(1)定义resource,关联model
from import_export import resources from d3.models import * from userapp.models import * from import_export.fields import Field class StudentResource(resources.ModelResource): #导出来的Excel,列名全是字段名,也就是英文的,但我想中文列名 id = Field(attribute='id', column_name='编号') name = Field(attribute='name', column_name='姓名') sfz = Field(attribute='sfz', column_name='身份证') name = Field(attribute='name', column_name=Student.name.field.verbose_name) new_field = Field(column_name='一个新的字段') class Meta: model = Student #导出的数据中加入Model里不存在的字段,dehydrate是固定关键字 @staticmethod def dehydrate_new_field(instance: Student): return '新字段内容' class UserResource(resources.ModelResource): class Meta: model = User ''' fields = ('id', 'name', 'author', 'price',) : 指定导出的字段 export_order = ('appid','name') : 指定导出的顺序 exclude = ('id',) : 不用导出的内容 import_id_fields = ('sfz',) #数据库已有人,现需要导入一个Excel来更新人,需把一字段设成主key,不然导入就变成新增了, 一般Excel里不会有数据库主键id的,所以这里用身份证sfz(假设sfz不重复,按sfz更新) ''' ''' 导出 Jg_dataset = JgResource().export() Jg_dataset.csv #导出csv数据 Jg_dataset.json #导出json数据 过滤导出 queryset = Jg.objects.filter(location='Helsinki') Jg_dataset = JgResource().export(queryset) '''
(2) 编写view
def export_demo(request): if request.method == 'POST': file_format = request.POST['file-format'] employee_resource = StudentResource() queryset = Student.objects.filter(xiangzhen='景山街道') dataset = employee_resource.export(queryset) if file_format == 'CSV': response = HttpResponse(dataset.csv, content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="exported_data.csv"' return response elif file_format == 'JSON': response = HttpResponse(dataset.json, content_type='application/json') response['Content-Disposition'] = 'attachment; filename="exported_data.json"' return response elif file_format == 'XLS (Excel)': response = HttpResponse(dataset.xls, content_type='application/vnd.ms-excel') response['Content-Disposition'] = 'attachment; filename="exported_data.xls"' return response return render(request, 'd3/export_demo.html')
html
{% block content %} <h3>Export Data</h3> <p>exporting from database</p> <form method="post" enctype="multipart/form-data"> {% csrf_token %} <p>Please select format of file.</p> <select name="file-format" class="form-control my-3"> <option selected>Choose format...</option> <option>CSV</option> <option>JSON</option> <option>XLS (Excel)</option> </select> <button class="btn btn-primary" type="submit">Export</button> </form> <a href="{% url 'd3:home' %}">Return Home View</a> {% endblock %}
二、导入
官网 django_import_export也有很多可定制方案,但错误消息很难以定制,例子如下:(但我不推荐)
from d3.resources import StudentResource
from tablib import Dataset
def import_demo(request): baseerrors=[] rowerrors=[] invaliderrors=[] context = {} if request.method == 'POST': file_format = request.POST['file-format'] employee_resource = StudentResource() dataset = Dataset() new_employees = request.FILES['importData'] if file_format == 'CSV': imported_data = dataset.load(new_employees.read().decode('utf-8'),format='csv') result = employee_resource.import_data(dataset, dry_run=True) elif file_format == 'JSON': imported_data = dataset.load(new_employees.read().decode('utf-8'),format='json') result = employee_resource.import_data(dataset, dry_run=True) elif file_format == 'xls': imported_data = dataset.load(new_employees.read(),format='xls') result = employee_resource.import_data(dataset, dry_run=True) if not result.has_errors(): employee_resource.import_data(dataset, dry_run=False) print(imported_data.__dict__) for data in imported_data : print(data[0],data[1],data[2]) baseerrors=result.base_errors rowerrors=result.row_errors() invaliderrors=result.invalid_rows context['baseerrors'] = baseerrors context['rowerrors'] = rowerrors context['invaliderrors'] = invaliderrors return render(request, 'd3/import_demo.html',context)
推荐的导入方案,利用tablib
from d3.resources import StudentResource
from tablib import Dataset
def import_can_custom(request):
context = {}
if request.method == 'POST':
file_format = request.POST['file-format']
employee_resource = StudentResource()
dataset = Dataset()
new_employees = request.FILES['importData']
imported_data = dataset.load(new_employees.read(),format='xls')
obj_list=[]
for data in imported_data :
print(data[0],data[1],data[2])
obj=Student(
name=data[1],
sfz=data[2],
)
obj_list.append(obj)
Student.objects.bulk_create(obj_list)
return render(request, 'd3/import_demo.html',context)
导入html
{% block content %} <h3>Import Data</h3> <p>importing to database</p> <form method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="importData"> <p>Please select format of file.</p> <select name="file-format" class="form-control my-3"> <option selected>Choose format...</option> <option>CSV</option> <option>JSON</option> <option>xls</option> </select> <button class="btn btn-primary" type="submit">Import</button> </form> <a href="{% url 'd3:home' %}">Return Home View</a> <div> {{baseerrors }} {{rowerrors }} {{invaliderrors }} </div>
另一个导入的例子
def uploadFile(request): if request.method == 'POST': dataset = Dataset() newStudent = request.FILES['myfile'] if not newStudent.name.endswith('xlsx'): messages.info(request, 'Wrong format') return render(request, 'file.html') loadedData = dataset.load(newStudent.read(), format='xlsx') for data in loadedData: value = Student( data[0], data[1], data[2], data[3], ) value.save() return render(request, 'file.html')