修改了form

This commit is contained in:
王思川 2024-06-19 02:03:59 +08:00
parent 0cd268452e
commit abf8064aba
6 changed files with 46 additions and 203 deletions

View File

@ -19,6 +19,12 @@ class EmployeeInformationForm(forms.ModelForm):
class EmployeeInformationAddForm(DepartmentSelectionForm, forms.ModelForm): class EmployeeInformationAddForm(DepartmentSelectionForm, forms.ModelForm):
primary_department = forms.ChoiceField(
choices=[('', '---------')] + [(dept.department_name, dept.department_name) for dept in PrimaryDepartment.objects.all()],
widget=forms.Select(attrs={'class': 'form-control'}),
label="一级部门"
)
class Meta: class Meta:
model = EmployeeInformation model = EmployeeInformation
fields = [field.name for field in EmployeeInformation._meta.fields if fields = [field.name for field in EmployeeInformation._meta.fields if
@ -33,6 +39,9 @@ class EmployeeInformationAddForm(DepartmentSelectionForm, forms.ModelForm):
'base_salary': forms.NumberInput() 'base_salary': forms.NumberInput()
} }
def __init__(self, *args, **kwargs):
super(EmployeeInformationAddForm, self).__init__(*args, **kwargs)
class EmployeeInformationEditForm(DepartmentSelectionForm, forms.ModelForm): class EmployeeInformationEditForm(DepartmentSelectionForm, forms.ModelForm):
class Meta: class Meta:

View File

@ -37,7 +37,7 @@ class CompanyEntity(models.Model):
verbose_name_plural = '公司主体信息登记表' verbose_name_plural = '公司主体信息登记表'
def __str__(self): def __str__(self):
return f"{self.company_name} - {self.entity_id}" return self.company_name
def get_historical_evolution(self): def get_historical_evolution(self):
return "\n".join([ return "\n".join([
@ -48,8 +48,7 @@ class CompanyEntity(models.Model):
class EntityChangeRecord(models.Model): class EntityChangeRecord(models.Model):
record_id = models.AutoField(primary_key=True, verbose_name='记录编号') record_id = models.AutoField(primary_key=True, verbose_name='记录编号')
company_entity = models.ForeignKey(CompanyEntity, on_delete=models.CASCADE, related_name='change_records', company_entity = models.ForeignKey(CompanyEntity, on_delete=models.CASCADE, related_name='change_records', verbose_name='公司主体', default=1)
verbose_name='公司主体', default=1)
change_date = models.DateField(verbose_name='变更日期') change_date = models.DateField(verbose_name='变更日期')
change_type = models.CharField(max_length=255, verbose_name='变更类型') change_type = models.CharField(max_length=255, verbose_name='变更类型')
content_before_change = models.TextField(verbose_name='变更前内容') content_before_change = models.TextField(verbose_name='变更前内容')
@ -82,13 +81,11 @@ class CompanyBankAccount(models.Model):
) )
account_id = models.AutoField(primary_key=True, verbose_name='账户ID') account_id = models.AutoField(primary_key=True, verbose_name='账户ID')
company_entity = models.ForeignKey(CompanyEntity, on_delete=models.CASCADE, related_name='bank_accounts', company_entity = models.ForeignKey(CompanyEntity, on_delete=models.CASCADE, related_name='bank_accounts', verbose_name='公司ID', default=1)
verbose_name='公司ID', default=1)
bank_name = models.CharField(max_length=255, verbose_name='开户行名称') bank_name = models.CharField(max_length=255, verbose_name='开户行名称')
account_number = models.CharField(max_length=255, verbose_name='账号') account_number = models.CharField(max_length=255, verbose_name='账号')
account_type = models.CharField(max_length=10, choices=ACCOUNT_TYPE_CHOICES, verbose_name='账户类型') account_type = models.CharField(max_length=10, choices=ACCOUNT_TYPE_CHOICES, verbose_name='账户类型')
account_status = models.CharField(max_length=10, choices=ACCOUNT_STATUS_CHOICES, verbose_name='账户状态', account_status = models.CharField(max_length=10, choices=ACCOUNT_STATUS_CHOICES, verbose_name='账户状态', default='active')
default='active')
class Meta: class Meta:
verbose_name = '公司银行账户' verbose_name = '公司银行账户'
@ -123,4 +120,4 @@ class SecondaryDepartment(models.Model):
unique_together = ('primary_department', 'secondary_department_name') unique_together = ('primary_department', 'secondary_department_name')
def __str__(self): def __str__(self):
return f"{self.secondary_department_name} ({self.primary_department})" return self.secondary_department_name

View File

@ -5,10 +5,9 @@ from ..org_mgnt.models import PrimaryDepartment
class GroupBusinessTargetForm(forms.ModelForm): class GroupBusinessTargetForm(forms.ModelForm):
primary_department = forms.ModelChoiceField( primary_department = forms.ChoiceField(
queryset=PrimaryDepartment.objects.all(), choices=[('', '---------')] + [(dept.department_name, dept.department_name) for dept in PrimaryDepartment.objects.all()],
widget=forms.Select(attrs={'class': 'form-control'}), widget=forms.Select(attrs={'class': 'form-control'}),
empty_label="选择一级部门",
label="一级部门" label="一级部门"
) )
@ -30,9 +29,6 @@ class GroupBusinessTargetForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(GroupBusinessTargetForm, self).__init__(*args, **kwargs) super(GroupBusinessTargetForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
self.fields['primary_department'].initial = kwargs['instance'].primary_department
print(f"Initial primary department: {self.fields['primary_department'].initial}") # 调试输出
def clean(self): def clean(self):
cleaned_data = super().clean() cleaned_data = super().clean()

View File

@ -3,10 +3,6 @@ from common.views import *
urlpatterns = [ urlpatterns = [
path('error_page/', error_page, name='error_page'), path('error_page/', error_page, name='error_page'),
path('download_excel_template/<str:template_name>/', download_template, name='download_template'),
path('download_excel_template/<str:template_name>/<str:fields>/', download_excel_template,
name='download_excel_template'),
path('common_excel_parse/', common_excel_parse, name='common_excel_parse'),
path('save_excel_data/', save_excel_table_data, name='save_excel_table_data'), path('save_excel_data/', save_excel_table_data, name='save_excel_table_data'),
path('load_secondary_departments/', load_secondary_departments, name='load_secondary_departments'), path('load_secondary_departments/', load_secondary_departments, name='load_secondary_departments'),

View File

@ -1,25 +1,16 @@
import json import json
import os
import urllib.parse
import uuid import uuid
import openpyxl
from django.apps import apps from django.apps import apps
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.shortcuts import render from django.shortcuts import render
from openpyxl import load_workbook
from django.conf import settings
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles import finders from django.http import JsonResponse, HttpResponse
from django.core.files.storage import default_storage
from django.http import FileResponse, HttpResponseNotFound, JsonResponse
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from rest_framework.serializers import ModelSerializer
from application import fac_mgnt
from application.fac_mgnt.models import InvoiceRecord from application.fac_mgnt.models import InvoiceRecord
from application.org_mgnt.models import SecondaryDepartment from application.org_mgnt.models import SecondaryDepartment, PrimaryDepartment
from application.pjt_mgnt.models import ProjectLedger from application.pjt_mgnt.models import ProjectLedger
@ -27,155 +18,6 @@ def error_page(request):
return render(request, 'error_page.html') return render(request, 'error_page.html')
@login_required
def download_template(request, template_name):
"""
该视图提供下载指定的Excel模板文件
参数:
request: HttpRequest对象
template_name: 请求下载的Excel模板文件的名称期望是一个字符串
fields: 包含字段信息的字典用于生成Excel文件的表头和格式
返回:
FileResponse对象允许用户下载生成的Excel文件
如果文件未找到则返回一个HttpResponseNotFound响应
"""
# 使用finders.find()根据文件名在Django的静态文件目录中查找文件的绝对路径
file_path = finders.find(f'excels/{template_name}')
# 如果文件路径不存在返回404响应
if not file_path:
return HttpResponseNotFound('<h1>文件未找到</h1>')
# 创建FileResponse对象设置为以附件形式下载设置MIME类型为Excel文件
response = FileResponse(open(file_path, 'rb'),
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
# 设置Content-Disposition头告诉浏览器这是一个需要下载的文件
# 使用urllib.parse.quote对文件名进行URL编码以确保文件名中包含的特殊字符不会引起问题
response['Content-Disposition'] = f'attachment; filename="{urllib.parse.quote(template_name)}"'
return response
@login_required
def download_excel_template(request, template_name, fields):
"""
该视图提供下载指定的Excel模板文件
参数:
request: HttpRequest对象
template_name: 请求下载的Excel模板文件的名称期望是一个字符串
fields: 包含字段信息的字典用于生成Excel文件的表头和格式
返回:
FileResponse对象允许用户下载生成的Excel文件
如果文件未找到则返回一个HttpResponseNotFound响应
"""
fields = json.loads(urllib.parse.unquote(fields).replace("'", '"'))
# 创建一个新的工作簿
wb = openpyxl.Workbook()
ws = wb.active
# 设置表头行
headers = [field['label'] for field in fields if field['is_add']]
ws.append(headers)
# 保存生成的Excel文件到指定路径
static_dir = os.path.join(settings.BASE_DIR, 'static', 'excels')
if not os.path.exists(static_dir):
os.makedirs(static_dir)
temp_file_path = os.path.join(static_dir, template_name)
wb.save(temp_file_path)
# 创建FileResponse对象设置为以附件形式下载设置MIME类型为Excel文件
response = FileResponse(open(temp_file_path, 'rb'),
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = f'attachment; filename="{urllib.parse.quote(template_name)}"'
return response
@csrf_protect
@login_required
def common_excel_parse(request):
"""
该函数用于解析上传的Excel文件并返回数据
Args:
request: HTTP请求对象包含上传的Excel文件
Returns:
JsonResponse: 包含解析后的Excel数据的JSON响应或包含错误消息的JSON响应
Raises:
N/A
"""
# 如果是POST请求并且有上传的文件
if request.method == 'POST' and request.FILES:
# 获取上传的Excel文件
excel_file = request.FILES.get('excel_file')
# 如果没有提供文件,返回错误响应
if not excel_file:
return JsonResponse({'error': '请先选择文件。'}, status=400)
# 获取模型名称
model_config = request.POST.get('model_config', '')
# 动态获取模型
try:
app_label, model_name = model_config.split('.')
model = apps.get_model(app_label, model_name)
except (LookupError, KeyError, ValueError):
return JsonResponse({'error': '模型配置错误。'}, status=400)
# 保存文件到服务器
file_name = default_storage.save(excel_file.name, excel_file)
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
try:
# 打开并解析Excel文件
workbook = load_workbook(file_path, data_only=True)
sheet = workbook.active
# 读取第一行作为表头
header_row = [cell.value for cell in sheet[1]]
# 获取字段名和 verbose_name排除索引字段
model_fields = [field.name for field in model._meta.fields if
not field.primary_key and field.verbose_name in header_row]
model_verbose_name = [field.verbose_name for field in model._meta.fields if
not field.primary_key and field.verbose_name in header_row]
if not all(item in model_verbose_name for item in header_row):
return JsonResponse({'error': '表头不匹配请使用正确的Excel上传模板。'}, status=400)
# 组成 fields_map
fields_map = dict(zip(model_fields, header_row))
fields_map_nf = dict(zip(header_row, model_fields))
# 创建一个映射将Excel表头映射到模型字段名
header_to_field_map = {header: fields_map_nf[header] for header in header_row}
instance_list = []
for row in sheet.iter_rows(min_row=2, values_only=True):
if not all(value is None for value in row):
instance_list.append({header_to_field_map[header]: value for header, value in zip(header_row, row)})
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({"table_data": instance_list, "fields_map": fields_map}, safe=False)
except Exception as e:
# 清理,删除上传的文件
os.remove(file_path)
return JsonResponse({'error': f'解析文件时出错: {str(e)}'}, status=500)
return JsonResponse({'error': '请求错误'}, status=400)
@csrf_protect @csrf_protect
@login_required @login_required
def save_excel_table_data(request): def save_excel_table_data(request):
@ -234,11 +76,19 @@ def save_excel_table_data(request):
@login_required @login_required
def load_secondary_departments(request): def load_secondary_departments(request):
primary_department_id = request.GET.get('primary_department_id') try:
secondary_departments = SecondaryDepartment.objects.filter(primary_department_id=primary_department_id).order_by( primary_department_name = request.GET.get('primary_department')
'secondary_department_name') primary_department = PrimaryDepartment.objects.get(department_name=primary_department_name)
return JsonResponse(list(secondary_departments.values('secondary_department_id', 'secondary_department_name')), secondary_departments = SecondaryDepartment.objects.filter(primary_department_id=primary_department.primary_department_id).order_by('secondary_department_name')
safe=False)
# 创建 HTML 字符串
options = '<option value="">选择二级部门</option>'
for dept in secondary_departments:
options += f'<option value="{dept.secondary_department_id}">{dept.secondary_department_name}</option>'
return HttpResponse(options)
except Exception as e:
return HttpResponse('')
@csrf_protect @csrf_protect

View File

@ -104,45 +104,39 @@
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
function updateSecondaryDepartments(primaryDepartmentId, selectedSecondaryDepartmentId = null) { function updateSecondaryDepartments(primaryDepartment, selectedSecondaryDepartment = null) {
var url = "{% url 'load_secondary_departments' %}"; var url = "{% url 'load_secondary_departments' %}";
$.ajax({ $.ajax({
url: url, url: url,
data: { data: {
'primary_department_id': primaryDepartmentId 'primary_department': primaryDepartment
}, },
success: function (data) { success: function (html) {
$('#id_secondary_department').html(''); $('#id_secondary_department').html(html);
$('#id_secondary_department').append('<option value="">选择二级部门</option>'); if (selectedSecondaryDepartment) {
$.each(data, function (key, value) { $('#id_secondary_department').val(selectedSecondaryDepartment);
$('#id_secondary_department').append('<option value="' + value.secondary_department_id + '">' + value.secondary_department_name + '</option>');
});
if (selectedSecondaryDepartmentId) {
$('#id_secondary_department').val(selectedSecondaryDepartmentId);
} }
} }
}); });
} }
$('#id_primary_department').change(function () { $('#id_primary_department').change(function () {
var primaryDepartmentId = $(this).val(); var primaryDepartment = $(this).val();
if (primaryDepartmentId) { if (primaryDepartment) {
updateSecondaryDepartments(primaryDepartmentId); updateSecondaryDepartments(primaryDepartment);
} else { } else {
$('#id_secondary_department').html('<option value="">选择二级部门</option>'); $('#id_secondary_department').html('<option value="">选择二级部门</option>');
} }
}); });
// 如果在页面加载时已选择一级部门,则加载相应的二级部门 // 如果在页面加载时已选择一级部门,则加载相应的二级部门
var initialPrimaryDepartmentId = $('#id_primary_department').val(); var initialPrimaryDepartment = $('#id_primary_department').val();
var initialSecondaryDepartmentId = $('#id_secondary_department').val(); var initialSecondaryDepartmentId = $('#id_secondary_department').val();
if (initialPrimaryDepartmentId) { if (initialPrimaryDepartment) {
updateSecondaryDepartments(initialPrimaryDepartmentId, initialSecondaryDepartmentId); updateSecondaryDepartments(initialPrimaryDepartment, initialSecondaryDepartmentId);
} }
});
</script>
<script type="text/javascript">
$(document).ready(function () {
// 动态生成id_seal_type的select选项 // 动态生成id_seal_type的select选项
var sealTypeOptions = [ var sealTypeOptions = [
{ value: '公章', text: '公章' }, { value: '公章', text: '公章' },
@ -174,5 +168,6 @@
console.log('选择的用印类型是:' + selectedSealType); console.log('选择的用印类型是:' + selectedSealType);
// 在这里添加其他需要的处理逻辑 // 在这里添加其他需要的处理逻辑
}); });
}); });
</script> </script>