![](/img/trans.png)
[英]DRF - ModelSerializer with a non-model write_only field
[英]Add a non-model field on a ModelSerializer in DRF 3
如何在 DRF 3 中的 ModelSerializer 上添加非模型字段? 即添加一個在我的實際 model 上不存在的字段?
class TestSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='vote_detail')
non_field = serializers.CharField() # no corresponding model property.
class Meta:
model = vote_model
fields = ("url", "non_field")
def create(self, validated_data):
print(direction=validated_data['non_field'])
但是 DRF 3 給我錯誤:
Got AttributeError when attempting to get a value for field `non_field` on serializer `TestSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Test` instance.
Original exception text was: 'Test' object has no attribute 'non_field'.
我搜索了 stack DRF - ModelSerializer with a non-model write_only field並找到了一些解決方案,但這些解決方案指的是我正在使用 DRF 3 的 DRF 2。這個版本有解決方案嗎?
class MySerializer(serializers.ModelSerializer):
write_only_char_field = serializer.CharField(write_only=True)
write_only_list_char_field = serializer.ListField(child=serializers.CharField(max_length=100, default=''), write_only=True)
empty_method_field = serializers.SerializerMethodField()
read_only_custom_model_field = serializers.CharField(source='custom_property', read_only=True)
def create(self, validated_data):
validated_data.pop('write_only_char_field', None)
validated_data.pop('write_only_list_char_field', None)
return super().create(validated_data)
serializers.CharField(write_only=True)
和serializers.ListField(...)
是一個很好的解決方案,可以為.create
和.update
方法提供額外的數據,可以是單個字符串或字符串列表(可以混合ListField
與其他序列化程序字段類型)。 使用此方法,您還可以定義def validate_write_only_char_field
以實現一些快速簡單的驗證。
serializers.SerializerMethodField()
允許您從序列化程序中定義的方法向序列化程序輸出添加一些自定義只讀字段。
read_only_custom_model_field
將使用模型上的方法來讀取一些數據,而不是嚴格的模型字段,而是自定義方法。 即
class MyModel(models.Model):
my_field = models.CharField(max_length=100)
@property
def custom_property(self):
return "Perform calculations, combine with related models, etc. etc."
class TestSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='vote_detail')
non_field = serializers.SerializerMethodField() # no corresponding model property.
class Meta:
model = vote_model
fields = ("url", "non_field")
def create(self, validated_data):
print(direction=validated_data['non_field'])
http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
或者瀏覽此鏈接
只是一個例子可能會幫助你。
class ExtensibleModelSerializerOptions(serializers.SerializerOptions):
"""
Meta class options for ModelSerializer
"""
def __init__(self, meta):
super(ExtensibleModelSerializerOptions, self).__init__(meta)
self.model = getattr(meta, 'model', None)
self.read_only_fields = getattr(meta, 'read_only_fields', ())
self.non_native_fields = getattr(meta, 'non_native_fields', ())
class ExtensibleModelSerializer(serializers.ModelSerializer):
_options_class = ExtensibleModelSerializerOptions
def restore_object(self, attrs, instance=None):
"""
Deserialize a dictionary of attributes into an object instance.
You should override this method to control how deserialized objects
are instantiated.
"""
for field in self.opts.non_native_fields:
attrs.pop(field)
return super(ExtensibleModelSerializer, self).restore_object(attrs, instance)
資料來源: https : //github.com/tomchristie/django-rest-framework/issues/951
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
資源:
如上所述,有兩種方法。 (1)添加模型屬性。 (2)添加模型字段。 我覺得在這篇文章中很好地解釋了在模型中添加@property。 如果您想讓模型“精益求精”,請使用“方法”字段。 Chandus的回答省略了一些關鍵點,但是:
class DeliveryItemSerializer(serializers.ModelSerializer):
product_name = serializers.SerializerMethodField(read_only=True)
def get_product_name(self, obj):
return obj.product.name
class Meta:
model = DeliveryItem
fields = (
(...your field names),
'product_name',)
get_
FIELD_NAME。 如果使用其他名稱,請在SerializerMethodField()
上使用method_name=method
name參數 在之前的所有回答中,我看到每個人都建議刪除那些不屬於 Django model..
所以這不是遵循單一責任主體
def create(self, validated_data):
pass
根據drf drf doc這個function只負責創建。
但如果您只想添加一些額外的字段作為響應,我們需要覆蓋
def to_representation(self,instance):
pass
像這樣在序列化程序中提供序列化程序字段,
name = serializers.BooleanField(allow_null=True, required=False, default=False)
然后像這樣在序列化程序中使用 create function
def create(self, validated_data):
validated_data.pop('name', None)
return super().create(validated_data)
現在你可以從前端輸入數據,它不會保存在 model 中。
要訪問該字段的數據,您將在 create function 視圖中獲取它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.