115 votes

Django Rest Framework - Comment ajouter un champ personnalisé dans ModelSerializer ?

J'ai créé un ModelSerializer et je veux ajouter un champ personnalisé qui ne fait pas partie de mon modèle.

J'ai trouvé une description pour ajouter des champs supplémentaires aquí et j'ai essayé ce qui suit :

customField = CharField(source='my_field')

Lorsque j'ajoute ce champ et que j'appelle mon validate() alors ce champ ne fait pas partie de la fonction attr dict. attr contient tous les champs du modèle spécifiés, sauf les champs supplémentaires. Je ne peux donc pas accéder à ce champ dans ma validation écrasée, n'est-ce pas ?

Lorsque j'ajoute ce champ à la liste des champs comme ceci :

class Meta:
    model = Account
    fields = ('myfield1', 'myfield2', 'customField')

alors je reçois une erreur parce que customField ne fait pas partie de mon modèle - ce qui est correct car je veux l'ajouter juste pour ce sérialiseur.

Y a-t-il un moyen d'ajouter un champ personnalisé ?

112voto

Idaho Points 24

En fait, il existe une solution sans toucher au modèle. Vous pouvez utiliser SerializerMethodField qui vous permettent de brancher n'importe quelle méthode à votre sérialiseur.

class FooSerializer(ModelSerializer):
    foo = serializers.SerializerMethodField()

    def get_foo(self, obj):
        return "Foo id: %i" % obj.pk

67voto

Tom Christie Points 8729

Tu fais la bonne chose, sauf que CharField (et les autres champs typés) sont destinés aux champs inscriptibles.

Dans ce cas, vous voulez juste un simple champ en lecture seule, donc à la place utilisez simplement :

customField = Field(source='get_absolute_url')

21voto

Lindauson Points 1041

...pour plus de clarté, si vous avez une méthode de modèle définie de la manière suivante :

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

Vous pouvez ajouter le résultat de l'appel de ladite méthode à votre sérialiseur comme suit :

class MyModelSerializer(serializers.ModelSerializer):
    model_method_field = serializers.CharField(source='model_method')

p.s. Comme le champ personnalisé n'est pas vraiment un champ de votre modèle, vous voudrez généralement le rendre en lecture seule, comme ceci :

class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )

14voto

va-dev Points 157

Voici la réponse à votre question. vous devez ajouter à votre compte modèle :

@property
def my_field(self):
    return None

maintenant vous pouvez utiliser :

customField = CharField(source='my_field')

source : https://stackoverflow.com/a/18396622/3220916

14voto

Ariel Points 145

Après avoir lu toutes les réponses ici, ma conclusion est qu'il est impossible de faire cela proprement. Il faut faire quelque chose de plus compliqué, comme créer un champ en écriture seule, puis remplacer la fonction validate y to_representation méthodes. Voici ce qui a fonctionné pour moi :

class FooSerializer(ModelSerializer):

    foo = CharField(write_only=True)

    class Meta:
        model = Foo
        fields = ["foo", ...]

    def validate(self, data):
        foo = data.pop("foo", None)
        # Do what you want with your value
        return super().validate(data)

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data["foo"] = whatever_you_want
        return data

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X