博主今天整理下Django框架中上傳Excel文件並讀取
博主是要在管理平台中新增用例的維護功能,想着通過上傳Excel文件來展示用例,下面是項目的路徑圖:
首先先建數據庫模型
model.py
可以根據上傳的日期區分目錄
1 # 用例文件 2 class CaseFile(models.Model): 3 case_class = models.ForeignKey(CaseClass) 4 file_name = models.FileField(upload_to='case/%Y/%m/%d/', verbose_name=u"文件名稱") 5 6 # 不注釋會報錯 7 # def __str__(self): 8 # return self.file_name 9 10 # 定義表名稱 11 class Meta: 12 verbose_name = "用例文件管理" 13 verbose_name_plural = "用例文件管理"
第二步
settings.py
配置文件上傳路徑
1 # 文件上傳配置 2 MEDIA_ROOT = os.path.join(BASE_DIR, 'upload/') 3 MEDIA_URL = '/upload/'
第三步
新建excel.py
根據excel的數據來提取自己需要的轉化成json格式,再組成數組
1 # -*- coding: utf-8 -*- 2 3 import xlrd 4 from MyPlatform.settings import MEDIA_ROOT 5 6 7 class ExcelImport: 8 def __init__(self, file_name, version): 9 # self.file_name = unicode(file_name, "utf-8") 10 # 文件路徑修改 11 self.file_name = (MEDIA_ROOT + str(file_name)).replace("/", "\\").decode("utf-8") 12 # print self.file_name 13 self.workbook = xlrd.open_workbook(self.file_name) 14 self.table = self.workbook.sheets()[0] 15 # 獲取總行數 16 self.nrows = self.table.nrows 17 18 # 版本號 19 self.version = version 20 21 self.cases = [] 22 23 def get_cases(self): 24 # 從第二行開始 25 for x in range(1, self.nrows): 26 row = self.table.row_values(x) 27 self.cases.append( 28 { 29 "case_class": row[3], 30 "name": row[4], 31 "code": row[0], 32 "level": row[5], 33 "condition": row[6], 34 "step": row[7], 35 "expected_result": row[9], 36 "version": self.version 37 } 38 )
第四步
forms.py
表單中新建文件表單
1 # 文件上傳表單 2 class FileForm(forms.Form): 3 file_name = forms.FileField(label=u"用例文件")
第五步
views.py
完成上傳的邏輯
1 # 用例導入 2 def case_excel_import(request, class_id): 3 # 判斷是否有session 4 username = request.session.get("username") 5 if username: 6 # 如果有session 獲取指定信息 7 if request.method == "POST": 8 ff = FileForm(request.POST, request.FILES) 9 # file_name = request.FILES.get('exampleInputFile') 10 if ff.is_valid(): 11 file_name = ff.cleaned_data["file_name"] 12 13 # 向數據庫中新增用例文件數據 14 case_file = CaseFile() 15 case_file.case_class_id = int(class_id) 16 case_file.file_name = file_name 17 case_file.save() 18 # print case_file.file_name 19 20 # 返回上傳成功 21 messages.add_message(request, messages.INFO, u"上傳成功!") 22 try: 23 build_case_import(file_name=case_file.file_name) 24 except Exception, e: 25 messages.add_message(request, messages.INFO, u"用例導入出錯:" + str(e)) 26 return HttpResponseRedirect("/caseList/" + class_id, {"ff": ff}) 27 else: 28 ff = FileForm() 29 messages.add_message(request, messages.INFO, u"請選擇文件!") 30 return HttpResponseRedirect("/caseList/" + class_id, {"ff": ff}) 31 else: 32 ff = FileForm() 33 return HttpResponseRedirect("/caseList/" + class_id, {"ff": ff}) 34 else: 35 # 如果沒有session,重定向到路由 /login/, 返回表單 36 uf = UserForm(request.POST) 37 # 重定向 38 return HttpResponseRedirect("/login/", {"uf": uf})
導入成功后前端回顯展示
前端代碼:
博主使用的是模態框
1 <div class="modal modal-default fade" id="modal-class"> 2 <div class="modal-dialog"> 3 <div class="modal-content"> 4 <div class="modal-header"> 5 <button type="button" class="close" data-dismiss="modal" aria-label="Close"> 6 <span aria-hidden="true">×</span></button> 7 <h4 class="modal-title">上傳用例文件</h4> 8 </div> 9 <div class="modal-body"> 10 <form class="form-group" enctype="multipart/form-data" method="post" action="/caseExcelImport/{{ case_class_one.id }}"> 11 {% csrf_token %} 12 {{ ff.as_p }} 13 <p class="help-block">請求確保文件格式正確 .</p> 14 <p class="help-block">用例模塊文件可下載 .</p> 15 <a href="/download/template" class="btn btn-default"> 16 <i class="fa fa-download"> 下載</i> 17 </a> 18 <p class="help-block">excel格式的文件 .</p> 19 <p class="help-block">文件中小模塊一欄填入最終所屬測試模塊 .</p> 20 <input type="submit" class="btn btn-default" value="上傳"/> 21 <button type="button" class="btn btn-default pull-right" data-dismiss="modal">取消</button> 22 </form> 23 </div> 24 </div> 25 </div> 26 </div>
列表展示代碼:
1 <div class="row"> 2 <div class="col-xs-12"> 3 <div class="box"> 4 <div class="box-header"> 5 <h3 class="box-title">用例模塊:{{ case_class_one.name }}</h3> 6 </div> 7 <!-- /.box-header --> 8 <div class="box-body"> 9 <p> 10 <button type="button" class="btn btn-default" data-toggle="modal" data-target="#modal-class" data-id="{{ case_class_one.id }}"> 11 <i class="fa fa-caret-square-o-right"> 導入</i> 12 </button> 13 </p> 14 <table id="testcase" class="table table-bordered table-striped"> 15 <thead> 16 <tr> 17 <th>用例編號</th> 18 <th>用例名稱</th> 19 <th>用例等級</th> 20 <th>期望結果</th> 21 <th>操作按鈕</th> 22 </tr> 23 </thead> 24 <tbody> 25 {% for case in cases %} 26 <tr> 27 <td>{{ case.code }}</td> 28 <td>{{ case.name }}</td> 29 <td>Level {{ case.level }}</td> 30 <td>{{ case.expected_result }}</td> 31 <td> 32 <a href="/caseInfo/{{ case_class_one.id }}/{{ case.case_id }}" > 33 <i class="fa fa-folder-open"> 查看</i> 34 </a> 35 </td> 36 </tr> 37 {% endfor %} 38 </tbody> 39 </table> 40 </div> 41 <!-- /.box-body --> 42 </div> 43 </div> 44 </div>
前端效果: