Django Rest框架:有没有办法在使用序列化器验证数据之前清理数据?

Gui*_*tia 5 serialization django-rest-framework

我有一个 API 端点 POST /data。接收到的数据以某种方式格式化,这与我将其存储在数据库中的方式不同。

我将使用 postgis 中的几何类型作为示例。

class MyPostgisModel(models.Model):
    ...
    position = models.PointField(null=True)
    my_charfield = models.CharField(max_length=10)
    ...
    errors = JSONField()  # Used to save the cleaning and validation errors

class MyPostgisSerializer(serializers.ModelSerializer):

    class Meta:
        model = MyPostgisModel
        fields = [
            ...
            "position",
            ...
            "my_charfield",
            "errors",
        ]

    def to_internal_value(self, data):
        ...
        # Here the data is coming in the field geometry but in the db, it's called
        # position. Moreover I need to apply the `GEOSGeometry(json.dumps(...))`
        # method as well.
        data["position"] = GEOSGeometry(json.dumps(data["geometry"]))
        return data

Run Code Online (Sandbox Code Playgroud)

问题是,类似的领域不仅有一个,position而且有很多。我想(也许是错误的)像这个validate_*field_name*计划一样,但为了清洁(clean_*field_name*)。

还有一个问题。在这个方案中,我仍然希望将其余数据保存在数据库中,即使某些字段引发了 ValidationError (例如:太长的 CharField )不是Primary_key/a unique_together 约束的一部分。并将相关错误保存到 JSONField 中,如下所示:

{
    "cleaning_errors": {
        ...
        "position": 'Invalid format: {
            "type": "NotAValidType",  # Should be "Point"
            "coordinates": [
                4.22,
                50.67
            ]
        }'
        ...
    },
    "validating_errors": {
        ...
        "my_charfield": "data was too long: 'this data is way too long for 10 characters'",
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

对于第一个问题,我想到这样做:

{
    "cleaning_errors": {
        ...
        "position": 'Invalid format: {
            "type": "NotAValidType",  # Should be "Point"
            "coordinates": [
                4.22,
                50.67
            ]
        }'
        ...
    },
    "validating_errors": {
        ...
        "my_charfield": "data was too long: 'this data is way too long for 10 characters'",
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我不确定这是一个好主意,也许有一种简单的方法来处理此类事情。

对于第二个问题;当没有primary_key格式错误时,捕获验证错误而不指定is_valid()返回True,我不知道如何继续。