Django REST Framework: adding additional field to ModelSerializer

前端 未结 8 1902
遇见更好的自我
遇见更好的自我 2020-11-28 01:33

I want to serialize a model, but want to include an additional field that requires doing some database lookups on the model instance to be serialized:

class          


        
相关标签:
8条回答
  • 2020-11-28 02:02

    With the last version of Django Rest Framework, you need to create a method in your model with the name of the field you want to add. No need for @property and source='field' raise an error.

    class Foo(models.Model):
        . . .
        def foo(self):
            return 'stuff'
        . . .
    
    class FooSerializer(ModelSerializer):
        foo = serializers.ReadOnlyField()
    
        class Meta:
            model = Foo
            fields = ('foo',)
    
    0 讨论(0)
  • 2020-11-28 02:04

    As Chemical Programer said in this comment, in latest DRF you can just do it like this:

    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 docs source

    0 讨论(0)
  • 2020-11-28 02:05

    You can change your model method to property and use it in serializer with this approach.

    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: With recent versions of rest framework (I tried 3.3.3), you don't need to change to property. Model method will just work fine.

    0 讨论(0)
  • 2020-11-28 02:05

    This worked for me. If we want to just add an additional field in ModelSerializer, we can do it like below, and also the field can be assigned some val after some calculations of lookup. Or in some cases, if we want to send the parameters in API response.

    In model.py

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

    In serializer.py

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

    Hope this could help someone.

    0 讨论(0)
  • 2020-11-28 02:15

    I think SerializerMethodField is what you're looking for:

    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

    0 讨论(0)
  • 2020-11-28 02:17

    if you want read and write on your extra field, you can use a new custom serializer, that extends serializers.Serializer, and use it like this

    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):
            # This must return a dictionary that will be used to
            # update the caller's validation data, i.e. if the result
            # produced should just be set back into the field that this
            # serializer is set to, return the following:
            return {
              self.field_name: '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']
    

    i use this in related nested fields with some custom logic

    0 讨论(0)
提交回复
热议问题