ModelSerializer przy użyciu właściwości modelu

103

Próbuję serializować model zawierający pole właściwości, które również chcę serializować.

models.py:

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    slug = models.AutoSlugField(populate_from='name')

    @property
    def ext_link(self):
        return "/".join([settings.EXT_BASE_URL, self.slug])

serializers.py:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ('name', 'ext_link')

Podczas próby uzyskania dostępu do powiązanego adresu URL otrzymuję wyjątek serializatora (KeyError) we ext_linkwłaściwości.

Jak mogę serializować ext_linknieruchomość?

Sander Smits
źródło

Odpowiedzi:

140

Ponieważ nie jest to pole modelu, należy je jawnie dodać do klasy serializatora

class MyModelSerializer(serializers.ModelSerializer):
    ext_link = serializers.Field()

    class Meta:
        model = MyModel
        fields = ('name', 'ext_link')
Tom Christie
źródło
5
Jedna uwaga : lista pól w Meta jest opcjonalna. Jeśli pominieszfields, w powyższym przykładzie otrzymasz wszystkieMyModelpola plusext_linkw zserializowanych danych. I to jest naprawdę niesamowite w przypadku złożonych modeli! EDYCJA : Przynajmniej tak jest w przypadkudjangorestframework==2.3.14.
e.thompsy
U mnie przy użyciu serializers.Field wystąpił błąd. „serializers.ReadOnlyField” działa, jeśli to_representation nie jest zdefiniowane, a widok jest tylko do odczytu.
Shashank Singla
15
Używam wersji 3.3.xi samo dodanie właściwości do pól nie jest wystarczające. Nadal muszę jawnie dodać poprzez ext_link = serializers.ReadOnlyField ().
jarmod
4
używając DRF 3.4.6 w Pythonie 3.5.1 i Django 1.10, dodawanie do pól działa dobrze.
Vaibhav Mishra
9
Uwaga: Używając fields = "__all__"również musiałem dodać myfield = serializers.ReadOnlyField()zgodnie z jarmod, używając wersji 3.7.7
Robert Townley
22

jak @Robert Townleykomentarz, to działa z wersją 3.8.2:

class MyModelSerializer(serializers.ModelSerializer):
    ext_link = serializers.ReadOnlyField()

    class Meta:
        model = MyModel
        fields = "__all__"
suhailvs
źródło