from django.core.exceptions import ValidationError from django.apps import apps 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[field] + ':' + field}】") 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: try: self.errors.append(f"第【{row_num + 1}】行【{self.reverse_field_mapping[field]}】字段输入错误: {error}") 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): if self.validate_data(): for row in self.data: row_data = {self.field_mapping[field]: value for field, value in row.items() if field in self.field_mapping} instance = self.model(**row_data) instance.save() 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