4

TLDR;

如何提供封装在字段类中的自定义、模型级别、字段验证?

其余的部分

我正在玩两个 JSONField 实现,(第一个第二个)。我正在为我的应用程序使用 Django 和 Django REST 框架的组合。我没有在表单级别做任何事情,只有一个暴露模型的 Web API。

理想情况下,我想在一个地方编写此验证,并使其在序列化程序级别 + 模型级别上运行(例如当我通过 a 时validators=[x])。我不能使用通常的validators=[x],因为我需要允许blank=True但还要验证空白值类型:|。

我有一个用例,我想验证我的JSONField. 使用validictory,我可以这样做:

  • 强行拨打self.full_clean()我的电话save()
  • 覆盖clean()我的模型并在那里进行验证

但是,我真正想做的是:将此验证添加到JSONField. 我想离开尽可能多的父Field类来做这件事。到目前为止,我有:

from django.db import models
from jsonfield import JSONField

class myValidatorField(JSONField):
    def validate(self, *args, **kwargs):
        # do some validation here
        super(myValidatorField, self).validate(*args, **kwargs)

class MyModel(models.Model):
    jsonstuff = myValidatorField(default=[])

    def save(self, *args, **kwargs):
        self.full_clean()
        super(MyModel, self).save(*args, **kwargs)

但是,我无法让它工作。此validate()方法不会在第二个实现中运行,而对于第一个,它会运行 4 次。

使困惑。

4

1 回答 1

1

我最终得到了这段代码,它似乎可以解决问题。

仅供参考,在我的用例中,我必须实现一个自定义 django rest 框架异常处理程序来捕获我所有的模型级ValidationError错误并将它们转换为 web400错误。

# fields.py
import validictory
from jsonfield import JSONField

class JSONSchemaField(JSONField):
    """A field that will ensure the data entered into it is valid JSON *and*
    internally validate to a JSON schema of your choice."""
    def __init__(self, *args, **kwargs):
        self.schema = kwargs.pop('schema', {})
        super(JSONSchemaField, self).__init__(*args, **kwargs)

    def clean(self, raw_value, model_instance):
        try:
            validictory.validate(raw_value, self.schema)
        except (validictory.FieldValidationError,
                validictory.SchemaError,
                validictory.validator.RequiredFieldValidationError) as err:
            raise ValidationError(err)
        return super(JSONSchemaField, self).clean(raw_value, model_instance)

# mixins.py
class ModelValidationMixin(object):
"""Django currently doesn't force validation on the model level
for compatibility reasons. We enforce here, that on each save,
a full valdation run will be done the for model instance"""
def save(self, *args, **kwargs):
    self.full_clean()
    super(ModelValidationMixin, self).save(*args, **kwargs)

# models.py
class MyModel(ModelValidationMixin):
    json = JSONSchemaField(default='[]', schema=SCHEMA)
于 2015-11-03T17:41:04.877 回答