70π
The basic pattern Iβve found useful is to put all my custom validation in clean()
and then simply call full_clean()
(which calls clean()
and a few other methods) from inside save()
, e.g.:
class BaseModel(models.Model):
def clean(self, *args, **kwargs):
# add custom validation here
super().clean(*args, **kwargs)
def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)
This isnβt done by default, as explained here, because it interferes with certain features, but those arenβt a problem for my application.
29π
I would override the validate_unique
method on the model. To make sure you ignore the current object when validating, you can use the following:
from django.db.models import Model, DateTimeField
from django.core.validators import NON_FIELD_ERRORS, ValidationError
class MyModel(Model):
start_date = DateTimeField()
end_date = DateTimeField()
def validate_unique(self, *args, **kwargs):
super(MyModel, self).validate_unique(*args, **kwargs)
qs = self.__class__._default_manager.filter(
start_date__lt=self.end_date,
end_date__gt=self.start_date
)
if not self._state.adding and self.pk is not None:
qs = qs.exclude(pk=self.pk)
if qs.exists():
raise ValidationError({
NON_FIELD_ERRORS: ['overlapping date range',],
})
ModelForm
will automatically call this for you through a full_clean()
, which you can use manually too.
PPR has a nice discussion of a simple, correct range overlap condition.
- [Django]-Django url tag multiple parameters
- [Django]-Django admin: how to sort by one of the custom list_display fields that has no database field
- [Django]-Docker/Kubernetes + Gunicorn/Celery β Multiple Workers vs Replicas?
16π
I think you should use this:
https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects
Just define clean() method in your model like this: (example from the docs link)
def clean(self):
from django.core.exceptions import ValidationError
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError('Draft entries may not have a publication date.')
# Set the pub_date for published items if it hasn't been set already.
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.datetime.now()
- [Django]-STATIC_ROOT vs STATIC_URL in Django
- [Django]-How do you set DEBUG to True when running a Django test?
- [Django]-Django: Error: You don't have permission to access that port
2π
I think this can help you,
We can create multiple validators like this use in models.
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from django.db import models
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
class MyModel(models.Model):
even_field = models.IntegerField(validators=[validate_even])
- [Django]-What is the purpose of apps.py in Django 1.9?
- [Django]-The QuerySet value for an exact lookup must be limited to one result using slicing. Filter error
- [Django]-Example of Django Class-Based DeleteView