import json from django.core.exceptions import ValidationError from django.shortcuts import render from django.contrib.auth.decorators import login_required from django.http import JsonResponse from django.views.decorators.csrf import csrf_protect from application.org_mgnt.models import SecondaryDepartment, PrimaryDepartment from django.http import HttpResponse from django.utils.http import quote from django.apps import apps from openpyxl import Workbook from openpyxl.utils import get_column_letter from datetime import datetime from django.utils.timezone import make_aware def error_page(request): return render(request, 'error_page.html') @csrf_protect @login_required def save_excel_table_data(request): if request.method == 'POST': try: data = json.loads(request.body) model_config = data.get('model_config') table_data = data.get('table_data') if not model_config or not table_data: return JsonResponse({'error': '缺少必要的参数'}, status=400) # 分割 model_config 以获取 app_label 和 model_name try: app_label, model_name = model_config.split('.') Model = apps.get_model(app_label, model_name) except (ValueError, LookupError): return JsonResponse({'error': '无效的 model_config'}, status=400) instances = [] for row_data in table_data: instance_data = {} for field_name, value in row_data.items(): field = Model._meta.get_field(field_name) if field.is_relation: related_model = field.related_model related_field_name_list = related_model._meta.fields for related_field_name in related_field_name_list: try: related_instance = related_model.objects.get(**{related_field_name.name: value}) value = related_instance instance_data[field_name] = value break except Exception: continue else: instance_data[field_name] = value instance = Model(**instance_data) try: instance.full_clean() instances.append(instance) except ValidationError as e: return JsonResponse({'error': f'数据校验错误: {e.message_dict}'}, status=400) # 批量保存数据 Model.objects.bulk_create(instances) return JsonResponse({'success': '数据保存成功'}, status=201) except json.JSONDecodeError: return JsonResponse({'error': '无效的JSON数据'}, status=400) except Exception as e: return JsonResponse({'error': f'保存数据时出错: {str(e)}'}, status=500) return JsonResponse({'error': '请求错误'}, status=400) @login_required def load_secondary_departments(request): try: primary_department_name = request.GET.get('primary_department') primary_department = PrimaryDepartment.objects.get(department_name=primary_department_name) secondary_departments = SecondaryDepartment.objects.filter(primary_department_id=primary_department.primary_department_id).order_by('secondary_department_name') # 创建 HTML 字符串 options = '' for dept in secondary_departments: options += f'' return HttpResponse(options) except Exception as e: return HttpResponse('') def export_data(request): model_config = request.GET.get('model_config') # 获取模型类 try: app_label, model_name = model_config.split('.') model = apps.get_model(app_label, model_name) except (ValueError, LookupError): return JsonResponse({'error': '无效的 model_config'}, status=400) # 获取过滤条件 filter_kwargs = {} for key, value in request.GET.items(): if key in ['model_config', 'csrfmiddlewaretoken']: # 忽略不相关的参数 continue if value: # 根据过滤条件的类型进行适当的转换 if 'date' in key or 'month' in key: try: filter_kwargs[key] = make_aware(datetime.strptime(value, '%Y-%m-%d')) except ValueError: filter_kwargs[key] = value + '-01' # Assuming YYYY-MM format else: filter_kwargs[key] = value queryset = model.objects.filter(**filter_kwargs) data = list(queryset.values()) # 获取模型字段的 verbose_name,排除主键 fields = [field for field in model._meta.fields if not field.primary_key] field_names = [field.name for field in fields] verbose_names = [field.verbose_name for field in fields] # 创建 Excel 工作簿 wb = Workbook() ws = wb.active # 写入表头 for col_num, verbose_name in enumerate(verbose_names, 1): col_letter = get_column_letter(col_num) ws[f'{col_letter}1'] = verbose_name # 写入数据 for row_num, record in enumerate(data, 2): for col_num, field_name in enumerate(field_names, 1): col_letter = get_column_letter(col_num) # 如果字段在记录中不存在,使用空字符串 ws[f'{col_letter}{row_num}'] = record.get(field_name, '') # 使用模型的 verbose_name 作为文件名的一部分 model_verbose_name = model._meta.verbose_name + '导出结果.xlsx' encoded_filename = quote(model_verbose_name) response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' wb.save(response) return response