from django.conf import settings from rest_framework import serializers from config.exceptions import AppError from apps.user.models import Institution, Department class CmsInstitutionSerializer(serializers.ModelSerializer): """CMS 机构(医院)序列化器。 - `code` 显式声明以去掉默认 UniqueValidator,改用自定义错误码校验唯一性。 - `banner_url` 返回可访问的完整 URL(未配置时为空串,便于管理端识别「未设图」)。 """ code = serializers.CharField(max_length=100) banner_url = serializers.SerializerMethodField() class Meta: model = Institution fields = [ 'id', 'code', 'name', 'type', 'level', 'province', 'city', 'banner_url', 'created_at', 'updated_at', ] read_only_fields = ['id', 'created_at', 'updated_at'] def get_banner_url(self, obj): if not obj.banner_url: return '' value = obj.banner_url if value.startswith(('http://', 'https://')): return value request = self.context.get('request') prefix = getattr(settings, 'STATIC_PUBLIC_PREFIX', '').rstrip('/') path = prefix + '/' + settings.STATIC_URL.strip('/') + '/' + value.lstrip('/') return request.build_absolute_uri(path) if request else path def validate_code(self, value): value = (value or '').strip() if not value: raise AppError('CMS_VALIDATION_ERROR', '机构编码不能为空', status_code=400) # 唯一性按 all_objects(含已停用)判定:编码唯一约束对软删行仍生效, # 否则同编码重建会在写库时撞唯一约束抛 500。 qs = Institution.all_objects.filter(code=value) if self.instance is not None: qs = qs.exclude(pk=self.instance.pk) if qs.exists(): raise AppError('CMS_INSTITUTION_CODE_EXISTS', '机构编码已存在(含已停用机构),如需复用请先恢复或更换编码', status_code=400) return value class CmsDepartmentSerializer(serializers.ModelSerializer): """CMS 科室(全局表,与机构无关)。""" name = serializers.CharField(max_length=100) class Meta: model = Department fields = ['id', 'name', 'category', 'created_at', 'updated_at'] read_only_fields = ['id', 'created_at', 'updated_at'] def validate_name(self, value): value = (value or '').strip() if not value: raise AppError('CMS_VALIDATION_ERROR', '科室名称不能为空', status_code=400) # 唯一性按 all_objects(含已停用)判定,避免同名重建在写库时撞唯一约束抛 500。 qs = Department.all_objects.filter(name=value) if self.instance is not None: qs = qs.exclude(pk=self.instance.pk) if qs.exists(): raise AppError('CMS_DEPARTMENT_NAME_EXISTS', '科室名称已存在(含已停用科室),如需复用请先恢复或更换名称', status_code=400) return value