Django中的Year字段

发布于 2021-01-29 15:22:29

我希望我的用户输入他们的出生年份。我不希望他们在表格中键入相同的内容,而是从可用选项中选择年份。我知道如果需要日期而不是年份,可以在模型中执行以下操作:

class MyModel(models.Model):

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

我可以使用表格来执行此操作,以使用户从datepicker中选择日期。

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

对于一年,我可以使用CharField/IntegerFieldchoicesSO答案中类似的方法。

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年不会更改可用选项。

您能帮我实现我想做的事情吗?

关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

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

    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的check框架不允许将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)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看