151 lines
6.0 KiB
Python
151 lines
6.0 KiB
Python
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 |