Django 项目实现数据导入功能

在使用django框架开发系统过程中遇到了需要将数据通过本地文件导入系统数据库的需求。查阅了许多资料后决定开始着手实现,并计划用本文记录实现过程。

本文主要参考了如下文章,记在前面以聊表对文章作者的感激之意:
《Django中从本地上传excel文件并将数据存储到数据库》
作者:petrolero
链接:https://www.cnblogs.com/petrolero/p/9909985.html*

一、需求和方案设计
1.需求

实现数据导入功能。具体地,通过在前端页面上传excel文件(.xls/.xlsx),将数据存入系统数据库中

2.方案设计
  1. 在对应的编辑页面设置‘导入’按钮,点击后将弹出一个导入操作窗口。
  2. 导入操作窗口设置两个功能,‘模板下载’和‘导入数据’。‘模板下载’提供预先设置好字段和数据有效性等的excel模板,‘导入数据’则向服务器提交用户上传的格式化地文件。
  3. 提交数据后,后台将进行一系列的数据检测、预处理和存储工作,并将根据执行结果返回信息,如导入成功、数据格式错误、文件格式错误等。

二、实现过程
1.前端页面
  1. ‘导入’按钮和导入操作窗口
    效果如下图。(实现方式可参考:https://zhidao.baidu.com/question/19419232.html)
    在这里插入图片描述
    在这里插入图片描述

  2. 导入操作窗口中的元素:
    在这里插入图片描述


    至此,前端页面部分编辑完成。

2.后台

数据导入功能的重点部分在与后台处理。现设用户已根据给定的模板编辑好数据,点击按钮将文件post至后台。
其实导入功能最大的问题就在于数据的格式不一定规范,虽然提供了设置好数据有效性的模板文件,但仍可能出现如存在合并单元行/列、列的顺序与模板不一致等情况。因此在后台需在尝试往数据库中存储数据之前对这类情况进行处理。下面贴出我的源码(删去了一些与我的项目有关的信息):

view.py

def file_upload(request):
    f = request.FILES.get('file')
    f_type = f.name.split('.')[-1]
    if f_type in ['xlsx', 'xls']:
        try:
            f_data = xlrd.open_workbook(file_contents=f.read()).sheet_by_name('data')
            rows = f_data.nrows

            # 设置有效数据的列数,并将excel data表的内容转存为一个二维数组
            valid_ncols = 4 
            f_content = [[0] * valid_ncols for i in range(rows)]
            for i in range(rows):
                for j in range(valid_ncols):
                    f_content[i][j] = f_data.cell(i, j).value

            # 检测传入数据的列名称是否正确
            head_dict = {'0': '预设列名0', '1': '预设列名1', '2': '预设列名2', '3': '预设列名3'}
            row_head = f_data.row_values(0)
            for head_index in range(valid_ncols):
                if str(row_head[head_index].replace(' ', '')) != head_dict[str(head_index)]:
                    message = 'excel文件内容列名与模板不对应,请上传与模板文件格式相同的文件'
                    return render(request,  'result.html', {'message': message)

            # 检测是否存在合并的列,并将合并的行补上对应的值
            for crange in f_data.merged_cells:
                rs, re, cs, ce = crange
                if cs <= valid_ncols and ce - cs > 1:
                    message = "导入失败!数据表格中存在合并的列,请核实"
                    return render(request,  'result.html', {'message': message)
                if cs <= valid_ncols:
                    for i in range(rs, re):
                        print(i, end=' ')
                        f_content[i][cs] = f_data.cell(rs, cs).value

            with transaction.atomic():
                for i in range(1, rows):
                    row_value = f_content[i]
					
					# 示例中,模板文件的的列1为数字,且可空。因此若excel文件中该列内容为空时,应将值设置为None
                    if row_value[1] == '':
                        row_value[1] = None
					# 示例中,以列0作为标识列,若某行的该列无信息,则代表该行数据无效,不存入数据库
                    if row_value[0] != '':
                        models.YourModel.objects.\
                            create(db_c0=row_value[0], db_c1=row_value[1], db_c2=row_value[2], db_c3=row_value[3], )
            message = '导入成功!'
        except:
            message = 'excel文件内容格式不规范,请上传与模板文件格式相同的文件'
    else:
        message = '上传文件类型错误,请上传excel文件(后缀为.xls或.xlsx)'
    return render(request,  'result.html', {'message': message)

至此,完成了简单的导入功能。

file_upload()中有许多部分可抽象出来单独写一个函数便于复用,因本文为笔者开发初版系统时的笔记,目前暂不实现,作为日后优化的目标之一。

欢迎与我讨论,若发现问题和不足之处,还请读者朋友不吝赐教。

  • 1
    点赞
  • 1
    评论
  • 8
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

<p style="color:#666666;"> <span style="font-size:14px;">本门课程重实战,将基础知识拆解到项目里,让你在项目情境里学知识。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">这样的学习方式能让你保持兴趣、充满动力,时刻知道学的东西能用在哪、能怎么用。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">平时不明白的知识点,放在项目里去理解就恍然大悟了。</span> </p> <p style="color:#666666;"> <span></span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>一、融汇贯通</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本视频采用了前后端分离的开发模式,前端使用Vue.js+Element UI实现了Web页面的呈现,后端使用Python 的Django框架实现数据访问的接口,前端通过Axios访问后端接口获得数据。在学习完本章节后,真正理解前后端的各自承担的工作。</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>二、贴近实战</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">本系列课程为练手项目实战:学生管理系统v4.0的开发,项目包含了如下几个内容:项目的总体介绍、基本功能的演示、Vuejs的初始化、Element UI的使用、在Django实现针对数据的增删改查的接口、在Vuejs中实现前端增删改查的调用、实现文件的上传、实现表格的分页、实现导出数据到Excel、实现通过Excel导入数据实现针对表格的批量化操作等等,所有的功能都通过演示完成、贴近了实战</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>三、课程亮点</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">在本案例中,最大的亮点在于前后端做了分离,真正理解前后端的各自承担的工作。前端如何和后端交互</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="color:#FF0000;font-size:14px;"><strong>适合人群:</strong></span> </p> <p style="color:#666666;"> <span style="font-size:14px;">1、有Python语言基础、web前端基础,想要深入学习Python Web框架的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">2、有Django基础,但是想学习企业级项目实战的朋友;</span> </p> <p style="color:#666666;"> <span style="font-size:14px;">3、有MySQL数据库基础的朋友</span> </p> <p style="color:#666666;"> <span style="font-size:14px;"> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><img alt="" src="https://img-bss.csdnimg.cn/202009070752197496.png" /><br /> </span> </p> <p style="color:#666666;"> <span style="font-size:14px;"><br /> </span> </p>
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

spongejerry

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值