Django REST Framework : ModelSerializer에 추가 필드 추가


148

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

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를 해당 호출 가능 항목에 연결해야합니까? 그것은 어떻게 생겼습니까?

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

답변:


225

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


19
이러한 필드에 유효성 검사를 추가 할 수 있습니까? 내 질문은 : post_save () 핸들러에서 유효성을 검사하고 처리 할 수있는 사용자 정의 POST 값을 수락하는 방법은 무엇입니까?
Alp

20
SerializerMethodField는 읽기 전용이므로 들어오는 POST / PUT / PATCH에는 작동하지 않습니다.
Scott A

24
DRF 3에서는으로 변경 field_name = serializers.SerializerMethodField()하고def get_field_name(self, obj):
화학 프로그래머

1
뭐죠 foo때 데프 SerializerMethodField? CreateAPIView를 사용할 때 foo가 저장 되었습니까? 그런 다음 is_named_bar () 메소드를 사용할 수 있습니까?
244boy

따라서이 답변을 기반으로 12 개의 추가 필드를 직렬 변환기에 전달하려면 각 필드에 대해 foo.field_custom?
AlxVallejo

41

이 방법으로 모델 방법을 속성으로 변경하고 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을 시도 했음)를 사용하면 속성을 변경할 필요가 없습니다. 모델 방법은 잘 작동합니다.


감사합니다 @Wasil! Django 모델의 속성 사용에 익숙하지 않으며 그 의미에 대한 올바른 설명을 찾을 수 없습니다. 설명 할 수 있습니까? @property 데코레이터의 요점은 무엇입니까?
Neil

2
즉,이 메소드를 속성처럼 호출 할 수 있습니다. 즉 , 데코레이터가없는 variable = model_instance.my_field것과 동일한 결과를 제공합니다 variable = model_instance.my_field(). 또한 : stackoverflow.com/a/6618176/2198571
Wasil Sergejczyk

1
적어도 장고 1.5.1 / djangorestframework == 2.3.10에서는 작동하지 않습니다. "필드"메타 속성에서 명시 적으로 참조하더라도 ModelSerializer가 적절성을 얻지 못합니다.
ygneo

9
실제 모델 필드가 아니므로 필드를 serializer에 추가해야합니다 . my_field = serializers.Field (source = 'my_field')
Marius

2
source='my_field' 더 이상 필요없고 예외를 제기
Guillaume Vincent

13

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

requestfoo의 값을 수정할 수있는 def foo (self) 안에 객체 를 갖고 싶다면 어떻게해야 합니까? (예 : request.user 기반 조회)
saran3h

1
foo의 가치가 요청에서 오는 경우 어떻게해야합니까?
saran3h

11

비슷한 질문 ( 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',
        )

10

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

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

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


2

이것은 나를 위해 일한 우리가 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 ')

**

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

**


0

으로 화학 프로그래머가 말했다 이 댓글 , 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 문서 소스

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.