DRF Serializer - Принимать поле, но не использовать его в `create` или `update`.

У меня есть модель Message, которая имеет FileField. Мой API принимает файлы в кодировке Base64, чтобы их можно было отправить вместе с другими данными.

Чтобы узнать имя файла и расширение, в сериализаторе есть еще одно поле attachment_filename, которое не является полем модели. Оно используется внутри Base64Field.

Я хочу иметь возможность проверить, есть ли оба attachment_filename, attachment или ни одного из них.

Проблема в том, что если attachment_filename только для чтения, то его нет в validate - data переменной.

С другой стороны, если это required=False, allow_null=True, сериализатор выдает ошибку при создании сообщения:

TypeError: ChatMessage() got an unexpected keyword argument 'attachment_filename'

Код:

class Base64File(Base64FileField):  # todo make accept a list of extensions (finite eg. pdf, xlsx, csv, txt )
    ALLOWED_TYPES = ['pdf', 'xlsx', 'png', 'jpg', 'jpeg', 'docx', 'doc', 'zip']

    def get_file_extension(self, filename, decoded_file):
        extension = self.get_full_name().split('.')[-1]
        return extension

    def get_file_name(self, decoded_file):
        attachment_filename = self.get_full_name()
        return '.'.join(attachment_filename.split('.')[:-1])

    def get_full_name(self):
        return self.context['request'].data['attachment_filename']  # todo validate name

class ChatMessageSerializer(serializers.ModelSerializer):
    attachment = Base64File(required=False)
    attachment_filename = serializers.CharField(required=False, allow_null=True)

    class Meta:
        model = ChatMessage
        fields = '__all__'


    def validate(self, data):
        """
        Validation of start and end date.
        """
        attachment = data.get('attachment')
        attachment_filename = data.get('attachment_filename')
        if bool(attachment) ^ bool(attachment_filename):
            raise serializers.ValidationError("Either none or both 'attachment' and 'attachment_filename' must be present")
        # del data['attachment_filename'] # works but dirty
        return data

Как заставить его работать?

EDIT

Мне удалось заставить его работать, добавив

del data['attachment_filename']

перед возвратом метода validate, но это кажется слишком "грязным".

Вы должны обработать это поведение в методе serializer.save, например, вы можете вывести его из validated_data вот так:

    def save(self, **kwargs):
        self.validated_data.pop("attachment_filename")

        return super().save(**kwargs)
Вернуться на верх