# -*- coding: utf-8 -*- # @Time : 2022/6/6 14:22 # @Author : 臧成龙 # @FileName: usual.py # @Software: PyCharm # -*- coding: utf-8 -*- import os from datetime import datetime from urllib.parse import unquote import openpyxl from django.http import FileResponse from django.shortcuts import get_object_or_404 from fuadmin.settings import BASE_DIR, STATIC_URL from ninja import Schema from openpyxl import load_workbook from .fu_auth import data_permission from .fu_ninja import FuFilters from .fu_response import FuResponse from .usual import get_user_info_from_token class ImportSchema(Schema): path: str def create(request, data, model): """ 创建新记录的函数。 参数: - request: 请求对象,用于获取用户信息。 - data: 创建记录的数据,可以是字典或者支持dict()方法的对象。 - model: Django ORM模型,指定要创建的对象类型。 返回值: - 创建成功的对象查询集合。 """ if not isinstance(data, dict): # 如果data不是字典类型,则转换为字典 data = data.dict() user_info = get_user_info_from_token(request) # 从请求中提取用户信息,并添加到数据中作为创建人、修改者和所属部门信息 data['creator_id'] = user_info['id'] data['modifier'] = user_info['name'] data['belong_dept'] = user_info['dept'] # 使用提供的模型和数据创建新记录 query_set = model.objects.create(**data) return query_set def batch_create(request, data, model): """ 批量创建模型实例。 参数: - request: HTTP请求对象,用于获取用户信息。 - data: 一个包含创建数据的列表,每个元素可以是字典或者具有dict方法的对象。 - model: Django模型类,用于实例化和批量创建。 返回值: - query_set: 批量创建后的模型实例查询集。 """ user_info = get_user_info_from_token(request) # 从请求中获取用户信息 data_list = [] for item in data: if not isinstance(item, dict): item = item.dict() # 如果item不是字典,则转换为字典 # 为每个创建的数据项添加默认的创建人、修改者和所属部门信息 item['creator_id'] = user_info['id'] item['modifier'] = user_info['name'] item['belong_dept'] = user_info['dept'] data_list.append(model(**item)) # 根据字典内容实例化模型对象并添加到列表中 query_set = model.objects.bulk_create(data_list) # 批量创建模型实例 return query_set def delete(id, model): """ 根据提供的ID和模型删除对象实例。 参数: - id: 要删除的对象的ID。 - model: 对象所属的模型类。 返回值: - 无返回值。 """ # 根据ID和模型获取对象实例,如果找不到则返回404错误页面 instance = get_object_or_404(model, id=id) # 删除对象实例 instance.delete() pass def update(request, id, data, model): """ 更新给定模型实例的数据。 参数: - request: HTTP请求对象,用于获取用户信息。 - id: 要更新的模型实例的ID。 - data: 包含更新数据的实例,应能转换为字典格式。 - model: 要更新的模型类。 返回值: - 更新后的模型实例。 """ dict_data = data.dict() # 将data转换为字典格式 user_info = get_user_info_from_token(request) # 从请求中获取用户信息 # 为更新的数据添加修改者信息 dict_data['modifier'] = user_info['name'] instance = get_object_or_404(model, id=id) # 获取指定ID的模型实例 # 遍历字典,将更新的数据设置到模型实例上 for attr, value in dict_data.items(): setattr(instance, attr, value) instance.save() # 保存更新 return instance # 返回更新后的实例 def retrieve(request, model, filters: FuFilters = FuFilters()): """ 根据提供的过滤条件从数据库中检索模型实例。 参数: - request: HttpRequest对象,用于获取请求信息。 - model: Django模型类,指定要检索的数据模型。 - filters: FuFilters类的实例,包含过滤条件。默认为FuFilters(),即无条件过滤。 返回值: - query_set: 一个Django QuerySet对象,包含根据过滤条件检索到的模型实例。 """ # 根据请求和过滤条件应用数据权限控制 filters = data_permission(request, filters) if filters is not None: # 将filters中的空字符串值转换为None for attr, value in filters.__dict__.items(): if getattr(filters, attr) == '': setattr(filters, attr, None) # 使用过滤条件查询模型实例 query_set = model.objects.filter(**filters.dict(exclude_none=True)) else: # 如果没有有效的过滤条件,则返回所有模型实例 query_set = model.objects.all() return query_set def export_data(request, model, scheme, export_fields): """ 导出数据为Excel文件。 参数: - request: HttpRequest对象,表示客户端请求。 - model: Django模型类,指定要导出数据的模型。 - scheme: 表示数据转换规则的对象,用于将ORM对象转换为字典。 - export_fields: 包含要导出的字段名的列表。 返回值: - FileResponse对象,提供下载Excel文件。 """ title_dict = {} # 根据export_fields列表获取字段的显示名称 for field in export_fields: field_obj = getattr(model, field).field title_dict[field] = field_obj.help_text qs = retrieve(request, model) list_data = [] # 将查询集中的每一项转换为指定格式的字典 for qs_item in qs: qs_item = scheme.from_orm(qs_item) dict_data = {} for item, value in title_dict.items(): dict_data[value] = getattr(qs_item, item) list_data.append(dict_data) # 创建并初始化Excel工作簿 wb = openpyxl.Workbook() ws = wb.active # 向Excel中写入数据 for index, data in enumerate(list_data): if index == 0: # 写入表头 ws.append(list(data.keys())) ws.append(list(data.values())) # 生成唯一的文件名并设置文件路径 file_name = datetime.now().strftime('%Y%m%d%H%M%S%f') + '.xlsx' current_ymd = datetime.now().strftime('%Y%m%d') file_path = os.path.join(STATIC_URL, current_ymd) file_url = os.path.join(file_path, file_name) # 确保导出文件的目录存在 if not os.path.exists(file_path): os.makedirs(file_path) # 保存Excel文件到指定路径 wb.save(file_url) # 返回供下载的文件响应 return FileResponse(open(file_url, "rb"), as_attachment=True) def import_data(request, model, scheme, data, import_fields): """ 导入数据到指定模型 参数: - request: HttpRequest对象,表示客户端请求 - model: Django模型类,数据将被导入到这个模型 - scheme: 一个函数,用于根据给定的数据字典创建模型实例 - data: 包含要导入文件信息的对象,比如上传的Excel文件 - import_fields: 一个列表,指定模型中需要导入的字段名 返回值: - FuResponse对象,包含导入结果的消息 """ title_dict = {} # 字段名与Excel列对应的字典 for field in import_fields: field_obj = getattr(model, field).field title_dict[field_obj.help_text] = field_obj.column # 文件路径处理 file_path = str(BASE_DIR) + unquote(data.path) # 加载Excel工作簿 wb = load_workbook(file_path) ws = wb.active # 获取活动工作表 title_value = [] for index_row, row in enumerate(ws.values): if index_row == 0: title_value = row # 读取Excel表头 else: dict_data = {} # 存储每一行数据转换后的字典 for index, cell in enumerate(row): title_cell = title_value[index] value = title_dict.get(title_cell) # 根据表头查找对应字段 if value is not None: dict_data[value] = cell print(dict_data) # 打印处理后的数据,用于调试 data = scheme(**dict_data) # 根据处理后的字典创建模型实例 create(request, data, model) # 在数据库中创建模型实例 return FuResponse(msg='导入成功') # 返回成功消息