Comment ajouter un champ non-modèle sur un ModelSerializer dans DRF 3? c'est-à-dire ajouter un champ qui n'existe pas sur mon modèle actuel?
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'])
Mais DRF 3 me donne l'erreur:
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'.
J'ai cherché pile DRF - ModelSerializer avec un champ write_only non-modèle et trouvé quelques solutions mais celles-ci se réfèrent à DRF 2 où j'utilise DRF 3. Existe-t-il une solution pour cela sur cette version?
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
ou passez par là lien
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)
La fonction serializers.CharField(write_only=True)
et serializers.ListField(...)
est une bonne solution pour fournir des données supplémentaires à vos méthodes .create
Et .update
, Sous la forme d'une chaîne unique ou d'une liste de chaînes (vous pouvez mélanger ListField
avec d'autres types de champs de sérialiseur). Avec cette méthode, vous pouvez également définir def validate_write_only_char_field
Pour implémenter une validation simple et rapide.
serializers.SerializerMethodField()
vous permet d'ajouter un champ personnalisé en lecture seule à la sortie de votre sérialiseur à partir d'une méthode définie sur le sérialiseur.
Le read_only_custom_model_field
Utiliserait une méthode sur votre modèle pour lire certaines données, pas strictement un champ de modèle, mais une méthode personnalisée. C'est à dire.
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."
Un simple exemple pourrait vous aider.
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
. . .
La source:
Django REST Framework: ajout d'un champ supplémentaire à ModelSerializer
Comme mentionné, il y a deux façons. (1) ajout d'une propriété de modèle. (2) ajouter un champ de modèle. Je pense que l'ajout d'une @ propriété au modèle a été bien expliqué dans ce post. Si vous voulez garder vos modèles "lean and mean", utilisez un champ Méthode. La réponse de Chandus omet cependant certains points cruciaux:
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_
Nom_champ. Si vous utilisez un autre nom, utilisez l'argument de nom method_name=method
Sur SerializerMethodField()