from rest_framework import serializers from basic_info import models as basic_models from django.contrib.auth.models import User import logging logger = logging.getLogger(__name__) class BaseSerializer(serializers.ModelSerializer): merchant = serializers.PrimaryKeyRelatedField( queryset=basic_models.Merchant.objects.all(), required=False # 创建时由视图层设置 ) def to_representation(self, instance): # 检查是否有 request context,以及是否需要进行权限验证 request = self.context.get('request') if request and hasattr(request, 'user') and hasattr(request.user, 'employee'): try: merchant = request.user.employee.merchant if instance.merchant != merchant: # 数据保护手段 logger.warning(f"用户 {request.user.username} 无权限访问对象 {type(instance).__name__} {instance.id}") raise PermissionError("无权限访问该对象") except AttributeError as e: # 用户没有 employee 属性 logger.warning(f"用户权限验证失败: {str(e)}") raise PermissionError("无权限访问该对象") result = super().to_representation(instance) if self.context.get('expand_merchant', False): result['merchant'] = { 'id': instance.merchant.id, 'name': instance.merchant.name } return result class QuickInputSerializer(serializers.ModelSerializer): class Meta: model = basic_models.QuickInput fields = ['id', 'name', 'value', 'group'] class ProductCategorySerializer(BaseSerializer): class Meta: model = basic_models.ProductCategory fields = '__all__' class ProductSerializer(BaseSerializer): # 图片字段:读取时返回完整 URL,写入时接受文件上传或 URL image = serializers.ImageField(required=False, allow_null=True) image_url = serializers.SerializerMethodField(read_only=True) class Meta: model = basic_models.Product fields = '__all__' def get_image_url(self, obj): """ 获取图片的完整 URL 返回: - 如果有图片:返回完整 URL(七牛云 CDN 地址) - 如果没有图片:返回 None """ if obj.image: request = self.context.get('request') if request: # 使用 request.build_absolute_uri 构建完整 URL return request.build_absolute_uri(obj.image.url) else: # 没有 request context 时,返回相对 URL # 七牛云存储会自动返回完整 URL return obj.image.url return None def to_representation(self, instance): result = super().to_representation(instance) result['category'] = { 'id': instance.category.id, 'name': instance.category.name } # 如果使用七牛云,image 字段已经是完整 URL,添加额外的 image_url 方便前端使用 # 前端可以使用 image 或 image_url,两者内容相同 return result class WareHouseSerializer(BaseSerializer): class Meta: model = basic_models.WareHouse fields = '__all__' class SupplierSerializer(BaseSerializer): class Meta: model = basic_models.Supplier fields = '__all__' class EmployeeSerializer(BaseSerializer): job_type = serializers.CharField(read_only=True) class Meta: model = basic_models.Employee fields = '__all__' class EmployeeTypeSerializer(BaseSerializer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 移除 unique_together 验证器中对 merchant 的要求 # 因为 merchant 会在 perform_create 中自动设置 for validator in self.validators: if hasattr(validator, 'fields') and 'merchant' in validator.fields: validator.fields = tuple(f for f in validator.fields if f != 'merchant') class Meta: model = basic_models.EmployeeType fields = '__all__' class CustomerSerializer(BaseSerializer): created_by = serializers.PrimaryKeyRelatedField( queryset=basic_models.Employee.objects.all(), required=False, ) class Meta: model = basic_models.Customer fields = '__all__' class VehicleTypeSerializer(BaseSerializer): class Meta: model = basic_models.VehicleType fields = '__all__' class BankAccountSerializer(BaseSerializer): class Meta: model = basic_models.BankAccount fields = '__all__' class DeviceInfoSerializer(BaseSerializer): class Meta: model = basic_models.DeviceInfo fields = '__all__' class VehicleTransportRecordSerializer(BaseSerializer): vehicle_type_name = serializers.CharField(source='vehicle_type.name', read_only=True) class Meta: model = basic_models.VehicleTransportRecord fields = '__all__' depth = 1 # 展开外键关系 class UserSerializerSimple(serializers.ModelSerializer): class Meta: model = basic_models.User fields = ['id', 'username', 'email', 'is_active', 'is_superuser', 'last_login'] class UserProfileSerializer(BaseSerializer): user = serializers.PrimaryKeyRelatedField( queryset=User.objects.all() ) user_detail = UserSerializerSimple(source='user', read_only=True) class Meta: model = basic_models.UserProfile fields = ['id', 'user', 'user_detail', 'merchant', 'description', 'created_at', 'updated_at'] extra_kwargs = { 'merchant': {'required': False} # 创建时由视图层设置 }