Nic*_*ick 12 django rest serializer django-rest-framework
我正在阅读Django REST Framework,我有一个使用SerializerMethodField()与getter序列化的模型.
但是,当我POST到此端点时,我希望能够设置此字段,但这不起作用,因为正如上面的文档所示,您无法写入SerializerMethodField.Django REST中是否有任何方法可以为您定义自定义getter方法的序列化器字段,以及自定义setter方法?
编辑:这是我正在尝试做的事情的来源.客户与用户具有一对一的关系.
class ClientSerializer(serializers.ModelSerializer):
email = serializers.SerializerMethodField()
def create(self, validated_data):
email = validated_data.get("email", None) # This doesn't work because email isn't passed into validated_data because it's a readonly field
# create the client and associated user here
def get_email(self, obj):
return obj.user.email
class Meta:
model = Client
fields = (
"id",
"email",
)
Run Code Online (Sandbox Code Playgroud)
Jul*_*ins 10
这是一个读/写序列化器方法字段:
class ReadWriteSerializerMethodField(serializers.SerializerMethodField):
def __init__(self, method_name=None, **kwargs):
self.method_name = method_name
kwargs['source'] = '*'
super(serializers.SerializerMethodField, self).__init__(**kwargs)
def to_internal_value(self, data):
return {self.field_name: data}
Run Code Online (Sandbox Code Playgroud)
我尝试使用Guilherme Nakayama da Silva和Julio Marins的答案来解决写入 SerializerMethodField 的问题。它适用于阅读和更新,但不适用于创作。
所以我根据他们的答案创建了自己的 WritableSerializerMethodField,它非常适合阅读、创建和写作。
class WritableSerializerMethodField(serializers.SerializerMethodField):
def __init__(self, **kwargs):
self.setter_method_name = kwargs.pop('setter_method_name', None)
self.deserializer_field = kwargs.pop('deserializer_field')
super().__init__(**kwargs)
self.read_only = False
def bind(self, field_name, parent):
retval = super().bind(field_name, parent)
if not self.setter_method_name:
self.setter_method_name = f'set_{field_name}'
return retval
def get_default(self):
default = super().get_default()
return {
self.field_name: default
}
def to_internal_value(self, data):
value = self.deserializer_field.to_internal_value(data)
method = getattr(self.parent, self.setter_method_name)
return {self.field_name: self.deserializer_field.to_internal_value(method(value))}
Run Code Online (Sandbox Code Playgroud)
然后我在我的序列化器中使用了它
class ProjectSerializer(serializers.ModelSerializer):
contract_price = WritableSerializerMethodField(deserializer_field=serializers.DecimalField(max_digits=12, decimal_places=2))
def get_contract_price(self, project):
return project.contract_price
def set_contract_price(self, value):
return value
Run Code Online (Sandbox Code Playgroud)
您需要使用另一种类型的字段:
class ClientSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='user.email')
def create(self, validated_data):
# DRF will create object {"user": {"email": "inputed_value"}} in validated_date
email = validated_data.get("user", {}).get('email')
class Meta:
model = Client
fields = (
"id",
"email",
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5541 次 |
| 最近记录: |