DRF Serializer - 接受字段但不要在“创建”或“更新”中使用它

DRF Serializer - Accept field but don't use it in `create` or `update`

我有一个模型 Message,它有一个 FileField。我的 API 接受 Base64 编码的文件,因此它们可以与其他数据一起发送。

要知道文件名和扩展名,序列化程序中还有一个字段 attachment_filename 不是模型字段。在Base64Field.

里面使用

我希望能够验证是否同时存在 attachment_filenameattachment 或 none。

问题是如果 attachment_filename 是只读的,它不会出现在 validate - data 变量中。

另一方面,如果它是 required=Falseallow_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

如何让它发挥作用?

编辑

我设法通过添加

使其工作
del data['attachment_filename']

validate 方法之前 return 但这似乎太“脏”了。

您应该在 serializer.save 方法中处理此行为,例如,您可以像这样从 validated_data 弹出它:

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

        return super().save(**kwargs)