验证日期字段,以便在 Django 中不需要未来的日期?

Tan*_*ay 8 python django django-models python-3.x

我正在为我的项目创建一个网站,我有一个名为的字段Purchase_Date

class Member_Registration(models.Model):
    Purchase_Date=models.DateField(max_length=10, help_text="Enter the date of purchase")
Run Code Online (Sandbox Code Playgroud)

如果用户选择了未来的日期,我想抛出一个错误。我该怎么做?

Mic*_*l B 10

由于Django的2.2,你不再需要创建一个自定义的验证了这一逻辑,因为limit_value现在可以是可调用的

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')
    )
Run Code Online (Sandbox Code Playgroud)

请注意,limit_value设置为date.today(a callable) 而不是date.today()。如果我们使用date.today(),则每当第一次加载代码时,它将使用该日期,从该点开始直到重新加载代码。使用date.today(一个可调用的)使这个动态化,并且每次调用验证器时它都会检索今天的日期。您现在在前端收到的错误现在将是“确保此值小于或等于 2019-12-02”(如果您将来阅读此内容,请将 2019-12-02 替换为今天的日期)。如果您想让您的错误消息更具体地针对该字段并具有自定义消息,则需要编写您自己的验证器的示例。

值得一提的是,如果您非常关心数据完整性,您可以在此字段上添加一个 CheckConstraint 以防止数据库也允许将来的日期。这将确保如果出于任何原因跳过验证,该值不能高于您的期望:

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'
            )
        ]
Run Code Online (Sandbox Code Playgroud)

如果我们尝试这样做,MemberRegistration(purchase_date=date(2099, 1, 1)).save()我们会得到错误:

django.db.utils.IntegrityError:关系“app_label_memberregistration”的新行违反检​​查约束“purchase_date_cannot_be_future_dated”详细信息:失败的行包含(2099-01-01)。


Kal*_*Kal 8

你想要的是一个验证器

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])
Run Code Online (Sandbox Code Playgroud)