XH_Digital_Management/common/views.py

151 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = '<option value="">选择二级部门</option>'
for dept in secondary_departments:
options += f'<option value="{dept.secondary_department_name}">{dept.secondary_department_name}</option>'
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