【问题标题】:How to set default inner serializer data in django-rest?如何在 django-rest 中设置默认的内部序列化程序数据?
【发布时间】:2021-03-22 23:24:12
【问题描述】:

我有两个简单的序列化器

class UserSerializer(Serializer);
    name = serializers.CharField(required=False, default='Mile')
    age =  serializers.IntegerField(required=False, default=25)

class AccountSerializer(Serializer):
    account_id = serializers.UUIDField(required=False, default=uuid4())
    user = UserSerializer()

如果未指定,我想在 AccountSerializer 中设置默认用户。 例如,

account = AccountSerializer(data={'account_id': uuid.UUID('e623429d-b1d1-4238-91b8-03e6f5ec58f1')})
account.is_valid()
account.data


  {
    'account_id': 'e623429d-b1d1-4238-91b8-03e6f5ec58f1',
    'user': {
        'name': 'Mike',                              # user must be default
        'age': 25
    }
}

我还想在“用户字段”中设置自己的值,并默认保留其他字段 例如,

account = AccountSerializer(data={'account_id': uuid.UUID('e623429d-b1d1-4238-91b8-03e6f5ec58f1'),
                                   'user': {'name': 'Julie'}})
    account.is_valid()
    account.data

{
        'account_id': 'e623429d-b1d1-4238-91b8-03e6f5ec58f1',
        'user': {
            'name': 'Julie',                              # user name must be 'Julie' but age by default
            'age': 25
        }
    }

我应该如何实现这个?请注意,我不会将模型保存到数据库中!我只需要检查传入的 json 并将字段设置为默认值(如果未设置)

【问题讨论】:

    标签: python-3.x django django-models serialization django-rest-framework


    【解决方案1】:

    您可以在序列化程序中直接设置default,最后调用serializer.validated_data。它会将数据保留在您的请求中,如果没有则自动填充默认值

    class UserSerializer(serializers.Serializer);
        name = serializers.CharField(required=False, default='Mike') #you want default is Mike?
        age =  serializers.IntegerField(required=False, default=25)
    
    class AccountSerializer(serializers.Serializer):
        account_id = serializers.UUIDField(required=False, default=uuid.UUID('e623429d-b1d1-4238-91b8-03e6f5ec58f1')) #this is your default uuid user
        user = UserSerializer(required=False, default={
        'name': 'Mike',
        'age': 25
    })
    

    如果您想要更多自定义来处理验证中的特殊逻辑。你可以试试覆盖validate

    class UserSerializer(serializers.Serializer):
        name = serializers.CharField(required=False)
        age = serializers.IntegerField(required=False)
    
        def validate_name(self, value):
            if not value:
                return 'Mike' #default name, or anything logic you want
            return value
    
        def validate_age(self, value):
            if not value:
                return 25 #default age
            return value
    
    class AccountSerializer(serializers.Serializer):
        account_id = serializers.UUIDField(required=False)
        user = UserSerializer()
    
        def validate_account_id(self, value):
            if not value:
                return uuid.UUID('e623429d-b1d1-4238-91b8-03e6f5ec58f1')
            return value
    

    在此之后,您调用

    serializer.is_valid(raise_exception=True)
    print(serializer.validated_data)
    

    serializer.validated_data 会有你想要的数据。

    【讨论】:

    • 如果我不打算保存模型,请告诉我是否需要使用序列化程序?我需要从客户端获取数据,将其转换为正确的 json(服务需要的 json)对其进行验证并向服务发送“发布”请求。如果客户没有指定必填字段,那么我需要用默认值填写它们
    • serializers.Serializer 是自定义序列化程序,它不与任何模型映射,也不保存到数据库。它用于验证,如果有效,发送这个或做任何你想做的事
    • 但是这个非常糟糕的实现。如果我没有 2 个字段而是 100 或 200 个字段怎么办?我是否必须为每个字段实施“if-condition”?所有字段都可以是可选的。
    • 您可以在序列化程序中直接设置default。在这一行中,default=25 age = serializers.IntegerField(required=False, default=25)。覆盖 validate 以处理您想要执行特殊逻辑的情况
    • 您的解决方案无法正常工作。例如,AccountSerializer(data={}).later 将返回 {'account_id': 'e623429d-b1d1-4238-91b8-03e6f5ec58f1'}。但是应该默认设置“用户”
    【解决方案2】:

    正如你所说,你没有模型

    1.serializer.py '''

    class UserSerializer(serializers.Serializer):
        name = serializers.CharField(required=False, default='Mile')
        age = serializers.IntegerField(required=False, default=25) #if key age is missing, value of age become 25
    
        def validate(self,data):
            #other wise you can set default value of age here,
            if data.get('name',None) is None: #this conditon will be true only when name = serializer.CharField(required=False)
                data['name']='Mike'
            if data.get('age',None)is None: #this conditon will be true only when age = serializer.IntergerField(required=False)
                    data['age']=25  
            return data
    

    ''' 视图.py '''

    serializer = UserSerializer(data={'name': 'cc', 'age': 14})
    serializer.is_valid()
    # True
    serializer.validated_data
    # {'id': 1, 'name': 'cc', 'age': 14} 
    

    ''' 或者如果您错过在 views.py 中指定年龄 '''

    serializer = UserSerializer(data={'name': 'cc'})
    serializer.is_valid()
    # True
    serializer.validated_data
    # { 'name': 'cc', 'age': 25} 
    

    '''

    【讨论】:

    • 但我需要完全不同。我需要在 AccountSerializer 中提供不完整的信息。如果那里没有定义用户,则设置默认用户。
    猜你喜欢
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 2011-03-08
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2011-09-30
    相关资源
    最近更新 更多