【问题标题】:DRF Serializer - Accept field but don't use it in `create` or `update`DRF 序列化器 - 接受字段,但不要在“创建”或“更新”中使用它
【发布时间】:2022-01-18 00:10:43
【问题描述】:

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

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

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

问题在于,如果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 方法返回之前,但这似乎太“脏”了。

【问题讨论】:

    标签: python django django-rest-framework django-serializer


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2021-03-19
      • 1970-01-01
      • 2021-07-14
      • 2018-08-10
      • 2020-04-16
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多