Django Excel sql 事務

1.原始sql

# 第一種
User.objects.raw(sql)

# 第二種
from django.db import connection
with connection.cursor() as cs:
    sql = """DESC {};""".format(table_name)
    cs.execute(sql)
    fields = cs.fetchall()
    
# 其它種查看文檔,聚合等等

2.事務

# 下面的代碼都在一個事務裏面執行,可以查看文檔
from django.db import transaction
try:
    with transaction.atomic():
        # 刪掉所有user id的信息
        IntentSlot.objects.filter(intent_id=intent_id).delete()
        # 對Excel文件進行解析
        data_list = ExcelHelper.load_excel(file_obj)
except Exception as e:
    return

3.操作excel

api
class IntentSlotFileApiView(APIView):
    def post(self, request):
        # 獲取傳過來的文件,必須的數據,slot_name,entity, slot_rule, entity, request_slot,default_value,is_required
        file_obj = request.data.get('filename')
        bot_id = request.data.get('bot_id')
        intent_id = request.query_params.get("intent_id")

        if not all([intent_id, file_obj]):
            return Response({"msg": "Incomplete parameters", "status": "fail"}, status=status.HTTP_400_BAD_REQUEST)

        # 文件名
        name = file_obj.name
        # 傳的不是excel就直接返回,不用解析
        if not (name.endswith('.xlsx') or name.endswith('.xls')):
            return Response({"msg": "Upload file is not Excel", "status": "fail"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # 下面的代碼都在一個事務裏面執行
            with transaction.atomic():
                # 刪掉所有user id的信息
                IntentSlot.objects.filter(intent_id=intent_id).delete()

                # 對Excel文件進行解析
                data_list = ExcelHelper.load_excel(file_obj)

                # 校驗上傳數據

        except Exception as e:
            return Response({"msg": repr(e), "status": "fail"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response({"msg": "Upload Success", "status": "success"}, status=status.HTTP_200_OK)

    def get(self, request):
        # 獲取參數
        intent_id = request.query_params.get("intent_id")
        if not intent_id:
            return Response({"msg": "Incomplete parameters", "status": "fail"}, status=status.HTTP_400_BAD_REQUEST)

        # 下載模板
        curr_time = datetime.date.today()
        sheet_name = 'intent_slot_%s_%s' % (intent_id, curr_time)

        try:
            # 根據intent_id查詢數據
            intent_slot_objs = IntentSlot.objects.filter(intent_id=intent_id)
            if intent_slot_objs:
                result_list = IntentSlotSerializer(intent_slot_objs, many=True).data
            else:
                result_list = []

            # 導出excel對象
            wb = ExcelHelper.export_excel("botzero_intent_slot", sheet_name, result_list)
            # 拼接表名
            file_name = "{}.xlsx".format(sheet_name)
            if os.path.exists(file_name):
                os.remove(file_name)

            response = HttpResponse(content_type='application/msexcel', status=status.HTTP_200_OK)
            response['Content-Disposition'] = 'attachment;filename={}'.format(file_name)
            wb.save(response)
            return response

        except Exception as e:
            return Response({'msg': repr(e), "status": "fail"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
excel_utils
# -*- coding: utf-8 -*-
import openpyxl
from django.db import connection
from openpyxl.styles import Alignment, Font

class ExcelHelper(object):
    @staticmethod
    def del_filed_by_table_name(table_name, results_list):
        if table_name == "temp_faq":
            for field_dict in results_list:
                del field_dict["state"]
                del field_dict["gmt_modify"]
                del field_dict["gmt_create"]
                del field_dict["question_id"]
                del field_dict["category_id"]
                del field_dict["user_id"]
                del field_dict["row_number"]

        elif table_name == "faq_word":
            for field_dict in results_list:
                del field_dict["faq_id"]
                del field_dict["id"]

    @staticmethod
    def load_excel(file_obj):
        wb = openpyxl.load_workbook(file_obj, data_only=True)
        sheets = wb.sheetnames
        worksheet = wb[sheets[0]]
        all_list, title_list = [], []

        for k, row in enumerate(worksheet.rows):
            # 獲取表的字段
            if k == 0:
                title_list = [cell.value for cell in row]
            # 獲取表的每行字段的值
            else:
                row_list = []
                for cell in row:
                    if isinstance(cell.value, bool):
                        value = str(cell.value).upper()
                    else:
                        value = cell.value
                    row_list.append(value)
                if any(row_list):
                    # 把字段名和字段值一一對應起來,生成字典並添加到row_list裏
                    all_list.append(dict(zip(title_list, row_list)))
        return all_list

    @staticmethod
    def export_excel(table_name, sheet_name, results_list):
        wb = openpyxl.Workbook()
        w = wb.create_sheet(sheet_name, 0)
        i = 1
        # results_list的從數據庫查詢出來的數據
        if not results_list:
            with connection.cursor() as cs:
                sql = """DESC {};""".format(table_name)
                cs.execute(sql)
                fields = cs.fetchall()
            field_dict = {}
            for field in fields:
                field_dict[field[0]] = None
            results_list.append(field_dict)

        # 根據表名刪除不必要的字段
        ExcelHelper.del_filed_by_table_name(table_name, results_list)

        for k, v in results_list[0].items():
            w.cell(row=1, column=i).value = k  # .replace("t_", "").replace("F_", "")
            s = chr(i + 64) + str(1)
            w[s].alignment = Alignment(horizontal='center', vertical='center')
            w[s].font = Font(bold=True)
            w.column_dimensions[chr(i + 64)].width = 35
            i = i + 1
        excel_row = 2
        # write data
        for i in range(0, len(results_list)):
            excel_col = 1
            for k, v in results_list[i].items():
                w.cell(row=excel_row, column=excel_col).value = v
                s = chr(excel_col + 64) + str(excel_row)
                w[s].alignment = Alignment(horizontal='center', vertical='center')
                excel_col = excel_col + 1
            excel_row = excel_row + 1
        return wb
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章