验证datefield所以它不会在django中使用未来的日期?

时间:2018-04-17 15:52:39

标签: python django python-3.x django-models

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

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

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

3 个答案:

答案 0 :(得分:2)

你想要的是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])

答案 1 :(得分:1)

您可以为此构建自己的validator

from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone as tz

def validate_date_not_in_future(value):
    if value > tz.now():
        raise ValidationError('date is in the future')

class MemberRegistration(models.Model):
    purchase_date = models.DateField(
        validators=[validate_date_not_in_future])

答案 2 :(得分:1)

从Django 2.2开始,您不再需要为此逻辑创建自定义验证器,因为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')
    )

请注意,limit_value设置为date.today(可调用)而不是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()),
                code='purchase_date_cannot_be_future_dated'
            )
        ]

如果我们尝试执行MemberRegistration(purchase_date=date(2099, 1, 1)).save(),我们将收到错误消息:

  

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