Можно ли переопределить SerializerMethodField для унаследованного Serializer?

Можно ли переопределить SerializerMethodField из унаследованного Serializer?

E.g.

# serializers.py

class BaseSerializer(serializers.ModelSerializer):
    custom = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ["pk", "custom"]

    def get_custom(self, obj):
        return "Base";

class ExtendedSerializer(BaseSerializer):
    custom = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ["pk", "custom"]

    def get_custom(self, obj):
        return "Extended";

Очевидно, что приведенный выше код не работает.

В настоящее время мне пришлось создать еще один Serializer и объявить новое SerializerMethodField для наследующих Serializers:

# serializers.py

class DefaultSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ["pk"]


class BaseSerializer(DefaultSerializer):
    custom = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ["pk", "custom"]

    def get_custom(self, obj):
        return "Base";

class ExtendedSerializer(DefaultSerializer):
    custom = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ["pk", "custom"]

    def get_custom(self, obj):
        return "Extended";

Но для моего случая использования было бы лучше, если бы я мог просто переопределить существующее поле SerializerMethodField, как в моем первом блоке кода.

На самом деле предложенное вами решение работает, и может быть еще более минимизировано до:

from rest_framework import serializers

class DefaultSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ['pk']

class BaseSerializer(DefaultSerializer):
    custom = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ['pk', 'custom']

    def get_custom(self, obj):
        return 'Base'

class ExtendedSerializer(BaseSerializer):

    def get_custom(self, obj):
        return 'Extended'

Таким образом, вам нужно упоминать поле custom как SerializerMethodField только один раз в BaseSerializer. Просто переопределив реализацию get_custom, можно получить данные, в которых ключ custom будет 'Base' при сериализации BaseSerializer и 'Extended' при сериализации ExtendedSerializer.

Действительно, если мы сериализуем экземпляры, мы получим:

>>> BaseSerializer(Item.objects.first()).data
{'pk': 1, 'custom': 'Base'}
>>> ExtendedSerializer(Item.objects.first()).data
{'pk': 1, 'custom': 'Extended'}
Вернуться на верх