Django 中的年份字段

新手上路,请多包涵

我希望我的用户输入他们的出生年份。我不希望他们在表单中输入相同的内容,而是从可用选项中选择年份。我知道如果我需要日期而不是年份,我可以在我的模型中做这样的事情:

 class MyModel(models.Model):

    birthday = models.DateField(null=True, blank=True)

我可以在表单中执行此操作,让用户从日期选择器中选择日期。

     birthday = forms.fields.DateField(widget=forms.widgets.DateInput(attrs={'type': 'date'}))

今年,我可以使用 CharField/IntegerFieldchoices 类似于在此 SO 答案中所做的。

 import datetime
YEAR_CHOICES = [(r,r) for r in range(1984, datetime.date.today().year+1)]

year = models.IntegerField(_('year'), choices=YEAR_CHOICES, default=datetime.datetime.now().year)

然而,问题是当前年份从 2018 年到 2019 年的变化不会改变可用选项。

你能帮助或提供提示来实现我想做的事情吗?

原文由 inquilabee 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 682
2 个回答

我最初的想法是编写一个可返回选择的可调用对象,它将针对每个请求进行评估。

 import datetime

def year_choices():
    return [(r,r) for r in range(1984, datetime.date.today().year+1)]

def current_year():
    return datetime.date.today().year

class MyModel(models.Model):
    year = models.IntegerField(_('year'), choices=year_choices, default=current_year)

但是这不起作用,因为 Django 的检查框架不允许将 year_choices 用作默认值。即使您可以破解要动态生成的选项,它也会有一个缺点,即 Django 每年都会在选项发生变化时尝试创建一个迁移。

您可以通过在表单级别生成选项来避免这种情况。您可以在模型中使用验证器来防止无效数据。请注意, MaxValueValidator 包装在一个函数中 max_value_current_year 以避免每年进行新的迁移。

 import datetime
from django.core.validators import MaxValueValidator, MinValueValidator

def current_year():
    return datetime.date.today().year

def max_value_current_year(value):
    return MaxValueValidator(current_year())(value)

class MyModel(models.Model):
    year = models.IntegerField(_('year'), validators=[MinValueValidator(1984), max_value_current_year])

def year_choices():
    return [(r,r) for r in range(1984, datetime.date.today().year+1)]

class MyForm(forms.ModelForm):
    year = forms.TypedChoiceField(coerce=int, choices=year_choices, initial=current_year)

原文由 Alasdair 发布,翻译遵循 CC BY-SA 4.0 许可协议

对于那些不喜欢长选择字段的人,即在@Alasdair 解决方案中,想象一下从 1984 年到 2019 年有一个选择字段,如此长的选择列表。拥有一个可以键入年份的字段,并且仍然可以增加或减少的方式怎么样。要以我的方式解决这个问题,请将 models.PositiveIntegerField 与 MinValueValidator 和 MaxValueValidator 一起使用,如下所示:

 import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models

def current_year():
    return datetime.date.today().year

def max_value_current_year(value):
    return MaxValueValidator(current_year())(value)

class EmployeesTrainings(models.Model):
    name = models.ForeignKey(employee, default='', blank=True, null=True, on_delete=models.CASCADE)
    training_name = models.TextField(max_length=200, default='', blank=False, null=False)
    training_year = models.PositiveIntegerField(
        default=current_year(), validators=[MinValueValidator(1984), max_value_current_year])

原文由 Ngatia Frankline 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题