Django Models: добавить проверку в настраиваемое поле

TLDR;

Как я могу предоставить пользовательский, модельный уровень, проверку поля, которая инкапсулирована в классе поля?

Остальные

Я играю с двумя реализациями JSONField ( первая, вторая). Я использую комбинацию Django и Django REST framework для моего приложения. Я ничего не делаю на уровне формы, только веб-API, демонстрирующий модель.

В идеале я хотел бы написать эту проверку в одном месте и запустить ее на уровне сериализатора + уровень модели (например, когда я передаю 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 раза.

Смущенный.

1 ответ

Я закончил с этим кодом, и, кажется, сработал.

К вашему сведению, в моем случае я должен был реализовать пользовательский обработчик исключений django rest framework, чтобы перехватить весь мой уровень модели ValidationError ошибки и конвертировать их в сеть 400 ошибки.

# 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)
Другие вопросы по тегам