Django Rest Framework-ModelSerializer에 사용자 정의 필드를 추가하는 방법


89

을 (를) 만들고 ModelSerializer내 모델의 일부가 아닌 사용자 정의 필드를 추가하고 싶습니다.

여기 에 추가 필드를 추가하는 설명을 찾았고 다음을 시도했습니다.

customField = CharField(source='my_field')

이 필드를 추가하고 내 validate()함수를 호출 하면이 필드는 attrdict의 일부가 아닙니다 . attr추가 필드를 제외하고 지정된 모든 모델 필드를 포함합니다. 따라서 덮어 쓴 유효성 검사에서이 필드에 액세스 할 수 없습니다.

이 필드를 다음과 같이 필드 목록에 추가하면 :

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

그런 다음 customField내 모델의 일부 가 아니기 때문에 오류가 발생 합니다.이 직렬 변환기에 대해서만 추가하고 싶기 때문에 올바른 것은 무엇입니까?

사용자 정의 필드를 추가하는 방법이 있습니까?


"하지만 내 필드가 serializer에 지정된 모델 필드 목록에 없으면 validate () attr-dictionary의 일부가 아닙니다."로 확장 할 수 있는지 확실하지 않습니다.
Tom Christie

또한 "내 모델에 customField 필드가 없다는 불만이 있습니다."라는 예외를 명시 적으로 설명해 주시겠습니까? 감사합니다! :)
Tom Christie

내 게시물을 업데이트했으며 이제 더 명확 해지기를 바랍니다. 난 그냥 내 모델의 일부가 아닌 필드 ... 추가 할 수있는 방법을 알고 싶어요


답변:


63

CharField(및 기타 입력 된 필드) 쓰기 가능한 필드를 제외하고는 올바른 일을하고 있습니다.

이 경우 간단한 읽기 전용 필드를 원하므로 대신 다음을 사용하십시오.

customField = Field(source='get_absolute_url')

4
감사합니다.하지만 쓰기 가능한 필드를 원합니다. 내 사용자를 식별하는 특정 사용자 토큰을 전달합니다. 하지만 내 모델에는 토큰이 아닌 사용자가 있습니다. 그래서 토큰을 전달하고 쿼리를 통해 사용자 개체로 "변환"하고 싶습니다.
Ron

다음은 소스가 모델 속성을 대상으로해야한다는 것입니다. 제 경우에는 지적 할 속성이 없습니다.
Ron

댓글의 사용자 / 토큰 비트를 이해하지 못합니다. 그러나 모델 인스턴스로 복원하기 전에 제거되는 serializer에 필드를 포함하려면 .validate()메서드를 사용 하여 속성을 제거 할 수 있습니다 . 참조 : django-rest-framework.org/api-guide/serializers.html#validation 사용 사례를 실제로 이해하지는 못하지만 필요한 작업을 수행합니다. 또는 a에 연결된 쓰기 가능한 필드를 원하는 이유 는 읽기 전용 속성 get_absolute_url?
Tom Christie

get_absolute_url문서에서 복사하여 붙여 넣은 것을 잊어 버리십시오. .NET에서 액세스 할 수있는 일반 쓰기 가능한 필드를 원합니다 validate(). 난 그냥이 필요 거라고 추측 source... 속성

그게 더 말이 되네요. :) 값은 유효성 검사를 위해 전달되어야하므로 직렬화를 인스턴스화하는 방법과 해당 값이 실제로 제공되는지 다시 확인합니다.
Tom Christie

82

실제로 모델을 전혀 건드리지 않고 해결책이 있습니다. SerializerMethodField어떤 메소드 든 시리얼 라이저에 연결할 수 있도록 사용할 수 있습니다 .

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

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

6
OP 가이 의견 에서 언급했듯이 , 그들은 쓰기 가능한 필드를 원하지만 SerializerMethodField그렇지 않습니다
email

14

... 명확성을 위해 다음과 같은 방식으로 정의 된 모델 메서드가있는 경우 :

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

다음과 같이 serializer에 해당 메서드를 호출 한 결과를 추가 할 수 있습니다.

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

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

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

3
쓰기 가능하게하려면 어떻게해야합니까?
Csaba Toth

1
@Csaba가 : 당신은 그냥 추가 콘텐츠를 저장 쓰기 사용자 정의 및 삭제 후크해야합니다 : 페이지의 "저장 및 삭제 후크를" "방법"에서 ( 여기에 ) 당신은 쓰기 사용자 정의해야합니다 perform_create(self, serializer), perform_update(self, serializer), perform_destroy(self, instance).
Lindauson 2015-08-24

13

여기에 귀하의 질문에 대한 답변. 모델 계정에 추가해야합니다.

@property
def my_field(self):
    return None

이제 다음을 사용할 수 있습니다.

customField = CharField(source='my_field')

출처 : https://stackoverflow.com/a/18396622/3220916


6
이 접근 방식은 합리적 일 때 사용했지만 특정 API 호출에만 실제로 사용되는 것에 대해 모델에 추가 코드를 추가하는 것은 좋지 않습니다.
Andy Baker

1
(가)에 대한 당신은 프록시 모델을 작성할 수 있습니다
ashwoods

10

보여주기 self.author.full_name위해 오류가 발생했습니다 Field. 다음과 함께 작동했습니다 ReadOnlyField.

class CommentSerializer(serializers.HyperlinkedModelSerializer):
    author_name = ReadOnlyField(source="author.full_name")
    class Meta:
        model = Comment
        fields = ('url', 'content', 'author_name', 'author')

6

Django Rest Framework의 마지막 버전에서는 추가하려는 필드의 이름으로 모델에 메서드를 만들어야합니다.

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

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

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

3

모델 직렬 변환기에 쓰기 가능한 사용자 정의 필드를 추가하는 솔루션을 찾고있었습니다. 이 질문에 대한 답변에서 다루지 않은이 질문을 찾았습니다.

실제로 간단한 직렬 변환기를 작성해야하는 것 같습니다.

class PassThroughSerializer(serializers.Field):
    def to_representation(self, instance):
        # This function is for the direction: Instance -> Dict
        # If you only need this, use a ReadOnlyField, or SerializerField
        return None

    def to_internal_value(self, data):
        # This function is for the direction: Dict -> Instance
        # Here you can manipulate the data if you need to.
        return data

이제이 Serializer를 사용하여 ModelSerializer에 사용자 정의 필드를 추가 할 수 있습니다.

class MyModelSerializer(serializers.ModelSerializer)
    my_custom_field = PassThroughSerializer()

    def create(self, validated_data):
        # now the key 'my_custom_field' is available in validated_data
        ...
        return instance

모델에 MyModel실제로 호출 된 속성이 my_custom_field있지만 유효성 검사기를 무시하려는 경우에도 작동합니다 .


그래서 my_custom_field가 MyModel의 속성이 아니면 작동하지 않습니까? 직렬 변환기 필드의 이름이 잘못 지정되어 MyModel인스턴스의 속성 또는 키와 일치하지 않을 수 있습니다 .
Sandeep Balagopal

2

여기에서 모든 답변을 읽은 후 내 결론은 이것을 깨끗하게 할 수 없다는 것입니다. 당신은 더럽게 플레이하고 write_only 필드를 생성하는 것과 같은 힘든 일을 한 다음 validateto_representation메서드 를 재정의해야 합니다. 이것은 나를 위해 일한 것입니다.

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