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)