[django] Django REST Framework : ModelSerializer에 추가 필드 추가

모델을 직렬화하고 싶지만 직렬화 할 모델 인스턴스에서 일부 데이터베이스 조회를 수행해야하는 추가 필드를 포함하고 싶습니다.

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

이것을하는 올바른 방법은 무엇입니까? 나는 것을 볼 당신이 여분의 “상황”에 전달할 수 있습니다 상황에 맞는 사전에 추가 필드에 통과 할 수있는 권리 대답은, 시리얼에? 이 방법을 사용하면 필요한 필드를 가져 오는 논리가 serializer 정의와 함께 포함되지 않으며 이는 모든 직렬화 된 인스턴스가 필요하기 때문에 이상적입니다 my_field. 다른 곳 DRF 시리얼 설명서는 말한다 “추가 필드가 모델에 어떤 속성이나 호출에 해당 할 수 있습니다.” 내가 말하는 것이 추가 필드입니까? 값 Foo을 반환하는 모델 정의 에서 함수를 정의해야 my_field하며 직렬 변환기에서 my_field를 해당 호출 가능 항목에 연결해야합니까? 그것은 어떻게 생겼습니까?

미리 감사드립니다. 필요한 경우 질문을 명확하게 설명하십시오.



답변

SerializerMethodField가 찾고있는 것 같습니다.

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


답변

이 방법으로 모델 방법을 속성으로 변경하고 serializer에서 사용할 수 있습니다.

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',)

편집 : 최신 버전의 나머지 프레임 워크 (3.3.3을 시도 했음)를 사용하면 속성을 변경할 필요가 없습니다. 모델 방법은 잘 작동합니다.


답변

Django Rest Framework의 마지막 버전에서는 추가하려는 필드 이름으로 모델에 메소드를 작성해야합니다. 대한 필요가 없습니다 @propertysource='field'오류를 발생시킵니다.

class Foo(models.Model):
    . . .
    def foo(self):
        return 'stuff'
    . . .

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

    class Meta:
        model = Foo
        fields = ('foo',)


답변

비슷한 질문 ( here )에 대한 나의 대답 이 유용 할 수 있습니다.

다음과 같은 방법으로 모델 방법을 정의한 경우 :

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

상기 메소드를 호출 한 결과를 시리얼 라이저에 다음과 같이 추가 할 수 있습니다.

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

ps 사용자 정의 필드는 실제로 모델의 필드가 아니므로 일반적으로 다음과 같이 읽기 전용으로 만들고 싶습니다.

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


답변

추가 필드에서 읽고 쓰려면 직렬화기를 확장하는 새로운 사용자 정의 직렬화기를 사용할 수 있습니다.

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']

나는 이것을 사용자 정의 로직과 관련된 중첩 필드에서 사용합니다.


답변

이것은 나를 위해 일한
우리가 ModelSerializer에 추가 필드를 추가 할 .If, 우리는 필드가 조회의 일부 계산 후 약간의 발을 할당 할 수 아래도 좋아 할 수 있습니다. 또는 API 응답으로 매개 변수를 보내려는 경우가 있습니다.

model.py에서

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



   **

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 ')

**

이것이 누군가를 도울 수 있기를 바랍니다.

**


답변

으로 화학 프로그래머가 말했다 이 댓글 , DRF 최근에 당신은 이런 식으로 작업을 수행 할 수 있습니다 :

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 문서 소스