I'm creating a website for my project and i have a field called Purchase_Date
:
class Member_Registration(models.Model):
Purchase_Date=models.DateField(max_length=10, help_text="Enter the date of purchase")
I want to throw an error if the user selects a date that is in the future. How do i go about this?
As of Django 2.2, you no longer have to create a custom validator for this logic because the limit_value
can now be a callable.
from datetime import date
from django.core.validators import MaxValueValidator
from django.db import models
from django.utils.translation import gettext_lazy as _
class MemberRegistration(models.Model):
purchase_date=models.DateField(
help_text=_('Enter the date of purchase'),
validators=[MaxValueValidator(limit_value=date.today)]
verbose_name=_('purchase date')
)
Note that the limit_value
is set to date.today
(a callable) and not date.today()
. If we used date.today()
, whenever the code is loaded for the first time, it will use that date from that point forward until the code is reloaded. Using date.today
(a callable) makes this dynamic and it will retrieve today's date each time the validator is called. The error you would now receive on the front end will now be "Ensure this value is less than or equal to 2019-12-02" (replace 2019-12-02 with today's date if you are reading this in the future). If you want to keep your error message more specific to the field and have a custom message, the examples of writing your own validator would be needed.
For what it is worth, if you are super concerned about data integrity, you can add a CheckConstraint on this field to prevent the database from allowing future dates as well. This would insure that if validation is skipped for any reason, the value cannot be above what you expect:
from datetime import date
from django.core.validators import MaxValueValidator
from django.db import models
from django.db.models.functions import Now
from django.utils.translation import gettext_lazy as _
class MemberRegistration(models.Model):
purchase_date=models.DateField(
help_text=_('Enter the date of purchase'),
validators=[MaxValueValidator(limit_value=date.today)]
verbose_name=_('purchase date')
)
class Meta:
constraints = [
models.CheckConstraint(
check=models.Q(purchase_date__lte=Now()),
name='purchase_date_cannot_be_future_dated'
)
]
If we tried to do MemberRegistration(purchase_date=date(2099, 1, 1)).save()
we would get the error:
django.db.utils.IntegrityError: new row for relation "app_label_memberregistration" violates check constraint "purchase_date_cannot_be_future_dated" DETAIL: Failing row contains (2099-01-01).
What you want is a validator:
from datetime import date
from django.core.exceptions import ValidationError
from django.db import models
def no_future(value):
today = date.today()
if value > today:
raise ValidationError('Purchase_Date cannot be in the future.')
class Member_Registration(models.Model):
Purchase_Date=models.DateField(help_text="Enter the date of purchase", validators=[no_future])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With