Kaspazza
Kaspazza

Reputation: 323

Django date validation, help needed

I tried to validate my DateField to accept only dates from today and future, but I don't know why it's accepting every passed date anyway.

My models.py file:

def present_or_future_date(value):
    if value < datetime.date.today():
        raise models.ValidationError("The date cannot be in the past!")
    return value

class Event(models.Model):
    title = models.CharField(max_length=50)
    text = models.TextField()
    date = models.DateField(default=datetime.now, validators=[present_or_future_date])
    duration = models.TextField(default='0', blank='true')
    created_at = models.DateTimeField(default=datetime.now, blank='true')

def __str__(self):
    return self.title

Upvotes: 11

Views: 12928

Answers (2)

Sardar Faisal
Sardar Faisal

Reputation: 673

To make sure the validation is performed, add constraints on the model in the Meta:

from django.db.models.functions import Now
from django.db import models

class Meta:
    constraints = [
        models.CheckConstraint(
            check=models.Q(date__gte=Now()),
            name='created_at_cannot_be_past_date'
        )
    ]

Upvotes: 1

May.D
May.D

Reputation: 1910

As Benjamin said, validators are added implicitly only to ModelForms. More documentation about validators here.

If you want to be sure that no object can be created with your date condition, you should override its save method like below. Also takecare that though Django will handle naive date objects, its way better to use django.utils.timezone.now

from django.db import models
import datetime
from django.core.exceptions import ValidationError

class Event(models.Model):
    title = models.CharField(max_length=50)
    text = models.TextField()
    date = models.DateField(default=datetime.date.today())
    duration = models.TextField(default='0', blank='true')
    created_at = models.DateTimeField(default=datetime.datetime.now(), blank='true')
    def save(self, *args, **kwargs):
        if self.date < datetime.date.today():
            raise ValidationError("The date cannot be in the past!")
        super(Event, self).save(*args, **kwargs)

Upvotes: 13

Related Questions