How do add a non-model field on a ModelSerializer in DRF 3? ie add a field that does not exist on my actual 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'])
But DRF 3 gives me the error:
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'.
I have searched stack DRF - ModelSerializer with a non-model write_only field and found a few solutions but these refer to DRF 2 where I'm using DRF 3. Is there a solution for this on this version?
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)
The serializers.CharField(write_only=True)
and serializers.ListField(...)
is a good solution to provide extra data to your .create
and .update
methods, as either a single string or a list of strings (you can mix ListField
with other serializer field types). With this method you can also define def validate_write_only_char_field
to implement some quick and simple validation.
serializers.SerializerMethodField()
allows you to add some custom read only field to your serializer output from a method defined on the serializer.
The read_only_custom_model_field
would use a method on your model to read some data, not strictly a model field, but a custom method. Ie
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
or go through this link
Just an example might help you.
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)
Source: https://github.com/tomchristie/django-rest-framework/issues/951
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
Source:
Django REST Framework: adding additional field to ModelSerializer
As mentioned there are two ways. (1) adding a model property. (2) adding a model field. I feel that adding a @property to model was explained well in this post. If you want to keep your models "lean and mean" use a Method field. Chandus answer omits some crucial points, though:
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 . If you use another name use the method_name=method
name argument on SerializerMethodField()
In all previous answer what i saw every one recommended to remove those added fields which is not the part of Django model..
So this is not follow single responsibility principal
def create(self, validated_data):
pass
According to drf drf doc this function only responsible for creation.
but if you want just add some extra fields in response we need to override
def to_representation(self,instance):
pass
Just give Serializer-field in serializer like this,
name = serializers.BooleanField(allow_null=True, required=False, default=False)
after then use create function in serializers like this
def create(self, validated_data):
validated_data.pop('name', None)
return super().create(validated_data)
Now you can enter the data from frontend-side and it will not save in the model.
And to access the data of this field you will get it in create function of view.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.