Django REST Framework: ajout de champs supplémentaires à ModelSerializer

Je souhaite sérialiser un modèle, mais je souhaite inclure un champ supplémentaire nécessitant certaines recherches dans l’instance de modèle à sérialiser:

class FooSerializer(serializers.ModelSerializer): my_field = ... # result of some database queries on the input Foo object class Meta: model = Foo fields = ('id', 'name', 'myfield') 

Quel est le bon moyen de le faire? Je vois que vous pouvez transmettre un “contexte” supplémentaire au sérialiseur, est-ce que la bonne réponse est de passer dans le champ supplémentaire d’un dictionnaire de contexte? Avec cette approche, la logique pour obtenir le champ dont j’ai besoin ne serait pas autonome avec la définition du sérialiseur, ce qui est idéal car chaque instance sérialisée aura besoin de my_field . Ailleurs dans la documentation des sérialiseurs DRF, il est indiqué que “des champs supplémentaires peuvent correspondre à toute propriété ou appelable sur le modèle”. Les champs supplémentaires sont-ils ce dont je parle? Dois-je définir une fonction dans la définition du modèle de Foo qui renvoie la valeur my_field et, dans le sérialiseur, je connecte my_field à cet appelable? A quoi cela ressemble-t-il?

Merci d’avance, heureux de clarifier la question si nécessaire.

Je pense que SerializerMethodField est ce que vous recherchez:

 class FooSerializer(serializers.ModelSerializer): my_field = serializers.SerializerMethodField('is_named_bar') def is_named_bar(self, foo): return foo.name == "bar" class Meta: model = Foo fields = ('id', 'name', 'my_field') 

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

Vous pouvez changer votre méthode de modèle en propriété et l’utiliser dans le sérialiseur avec cette approche.

 class Foo(models.Model): . . . @property def my_field(self): return stuff . . . class FooSerializer(ModelSerializer): my_field = serializers.ReadOnlyField(source='my_field') class Meta: model = Foo fields = ('my_field',) 

Edit: Avec les versions récentes de Rest Framework (j’ai essayé 3.3.3), vous n’avez pas besoin de changer de propriété. La méthode du modèle fonctionnera très bien.

Avec la dernière version de Django Rest Framework, vous devez créer une méthode dans votre modèle avec le nom du champ que vous souhaitez append. Pas besoin de @property et de source='field' générer une erreur.

 class Foo(models.Model): . . . def foo(self): return 'stuff' . . . class FooSerializer(ModelSerializer): foo = serializers.ReadOnlyField() class Meta: model = Foo fields = ('foo',) 

Ma réponse à une question similaire ( ici ) pourrait être utile.

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 append le résultat de l’appel de cette méthode à votre sérialiseur comme suit:

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

ps Comme le champ personnalisé n’est pas vraiment un champ dans 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', ) 

Si vous voulez lire et écrire sur votre champ supplémentaire, vous pouvez utiliser un nouveau sérialiseur personnalisé, qui étend serializers.Serializer, et l’utiliser comme ça

 class ExtraFieldSerializer(serializers.Serializer): def to_representation(self, instance): # this would have the same as body as in a SerializerMethodField return 'my logic here' def to_internal_value(self, data): return 'Any python object made with data: %s' % data class MyModelSerializer(serializers.ModelSerializer): my_extra_field = ExtraFieldSerializer(source='*') class Meta: model = MyModel fields = ['id', 'my_extra_field'] 

Je l’utilise dans des champs nesteds connexes avec une logique personnalisée

Comme l’a indiqué Chemical Programer dans ce commentaire , dans le dernier DRF, vous pouvez le faire comme ceci:

 class FooSerializer(serializers.ModelSerializer): extra_field = serializers.SerializerMethodField() def get_extra_field(self, foo_instance): return foo_instance.a + foo_instance.b class Meta: model = Foo fields = ('extra_field', ...) 

DRF source de documents

Cela a fonctionné pour moi . Si nous voulons simplement append un champ supplémentaire dans ModelSerializer, nous pouvons le faire comme ci-dessous et le champ peut également être assigné à des valeurs après quelques calculs de recherche. Ou dans certains cas, si nous voulons envoyer les parameters dans la réponse de l’API.

En model.py

 class Foo(models.Model): """Model Foo""" name = models.CharField(max_length=30, help_text="Customer Name") ** 

Dans serializer.py

**

 class FooSerializer(serializers.ModelSerializer): resortingeved_time = serializers.SerializerMethodField() @classmethod def get_resortingeved_time(self, object): """getter method to add field resortingeved_time""" return None class Meta: model = Foo fields = ('id', 'name', 'resortingeved_time ') 

**

J’espère que cela pourrait aider quelqu’un

**