Метод clean
Метод clean применяется к экземпляру модели и выполняет пользовательскую валидацию данных, которая не может быть покрыта стандартными валидаторами полей. Он позволяет проверять взаимосвязи между полями, а также выполнять сложные проверки целостности данных. Метод вызывается автоматически при вызове full_clean или при сохранении модели через ModelForm. При обнаружении ошибок метод должен выбрасывать исключение ValidationError с соответствующими сообщениями.
Синтаксис
class MyModel(models.Model):
# поля модели
def clean(self):
# пользовательская валидация
if condition:
raise ValidationError('Error message')
Пример
Давайте создадим модель статьи с проверкой того, что дата публикации не может быть раньше даты создания:
from django.db import models
from django.core.exceptions import ValidationError
class Article(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
published_at = models.DateTimeField(null=True, blank=True)
def clean(self):
if self.published_at and self.created_at:
if self.published_at < self.created_at:
raise ValidationError('Publication date cannot be earlier than creation date')
Теперь выполним валидацию экземпляра модели:
from myapp.models import Article
from datetime import datetime, timedelta
from django.core.exceptions import ValidationError
article = Article(
title='New article',
published_at=datetime.now() - timedelta(days=1)
)
try:
article.full_clean()
except ValidationError as e:
print(e.message_dict)
Результат выполнения кода:
{'__all__': ['Publication date cannot be earlier than creation date']}
Пример
Давайте добавим проверку уникальности комбинации полей 'title' и 'category':
from django.db import models
from django.core.exceptions import ValidationError
class Article(models.Model):
title = models.CharField(max_length=100)
category = models.CharField(max_length=50)
def clean(self):
if Article.objects.filter(
title=self.title,
category=self.category
).exclude(pk=self.pk).exists():
raise ValidationError('Article with this title and category already exists')
Выполним проверку на дубликат:
from myapp.models import Article
from django.core.exceptions import ValidationError
Article.objects.create(title='Django Guide', category='Programming')
duplicate = Article(title='Django Guide', category='Programming')
try:
duplicate.full_clean()
except ValidationError as e:
print(e.message_dict)
Результат выполнения кода:
{'__all__': ['Article with this title and category already exists']}
Пример
Давайте создадим модель заказа с проверкой минимальной суммы:
from django.db import models
from django.core.exceptions import ValidationError
class Order(models.Model):
user = models.CharField(max_length=50)
total = models.DecimalField(max_digits=10, decimal_places=2)
def clean(self):
if self.total < 1:
raise ValidationError({'total': 'Order total must be at least 1'})
Протестируем валидацию с некорректной суммой заказа:
from myapp.models import Order
from django.core.exceptions import ValidationError
order = Order(user='John', total=0.50)
try:
order.full_clean()
except ValidationError as e:
print(e.message_dict)
Результат выполнения кода:
{'total': ['Order total must be at least 1']}
Смотрите также
-
метод
full_clean,
который выполняет все этапы валидации модели -
метод
clean_fields,
который валидирует отдельные поля модели -
метод
validate_unique,
который проверяет уникальность полей модели -
метод
validate_constraints,
который проверяет ограничения модели