XH_Digital_Management/excel_parser/utils.py

81 lines
3.3 KiB
Python
Raw Permalink Normal View History

from django.core.exceptions import ValidationError
from django.apps import apps
2024-06-18 04:42:01 +08:00
from django.db import transaction
class ExcelDataSaver:
def __init__(self, model_name, data):
app_name, model_name = model_name.split('.')
self.model = apps.get_model(app_name, model_name)
self.data = data
self.field_mapping, self.reverse_field_mapping = self._generate_field_mapping()
self.errors = []
def _generate_field_mapping(self):
field_mapping = {}
reverse_field_mapping = {}
for field in self.model._meta.get_fields():
if hasattr(field, 'verbose_name'):
field_mapping[field.verbose_name] = field.name
reverse_field_mapping[field.name] = field.verbose_name
return field_mapping, reverse_field_mapping
def validate_data(self):
for row_num, row in enumerate(self.data):
instance = self.model()
for field, value in row.items():
actual_field = self.field_mapping.get(field)
if not actual_field:
self.errors.append(
f"第【{row_num + 1}】行找不到对应的模型字段: 【{self.reverse_field_mapping.get(field, field)}")
continue
if value is None or value == '' or value == '-':
continue # 跳过空值的处理
setattr(instance, actual_field, value)
# 在设置所有字段值之后再调用 full_clean
try:
instance.full_clean()
except ValidationError as e:
for field, errors in e.message_dict.items():
for error in errors:
2024-06-18 02:48:18 +08:00
try:
2024-06-18 04:42:01 +08:00
self.errors.append(f"第【{row_num + 1}】行【{self.reverse_field_mapping[field]}】输入错误: {error}")
2024-06-18 02:48:18 +08:00
except KeyError:
self.errors.append(f"第【{row_num + 1}】行,错误原因: {error}")
except Exception as e:
self.errors.append(f"其他错误: {e}")
return len(self.errors) == 0
def save_data(self):
2024-06-18 04:42:01 +08:00
errors = []
row_counter = 0
if self.validate_data():
2024-06-18 04:42:01 +08:00
try:
with transaction.atomic():
for row in self.data:
row_data = {self.field_mapping[field]: (None if value == '-' else value) for field, value in row.items() if field in self.field_mapping}
2024-06-18 04:42:01 +08:00
instance = self.model(**row_data)
instance.save()
row_counter += 1
except Exception as e:
errors.append(f"第【{row_counter + 1}】行保存错误: {e}")
transaction.rollback() # 回滚事务
self.errors.extend(errors)
return False
return True
return False
def get_errors(self):
return self.errors
def add_custom_validation(self, custom_validation_func):
self.custom_validation_func = custom_validation_func
self.validate_data = self._validate_data_with_custom
def _validate_data_with_custom(self):
basic_valid = self.validate_data()
custom_valid = self.custom_validation_func(self.data)
return basic_valid and custom_valid