Django 中的年份字段 [英] Year Field in Django

查看:24
本文介绍了Django 中的年份字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want my users to enter their birth year. I don't want them to type the same in the form rather select the year from available options. I known that I can do something like this in my model if I needed to date instead of year:

class MyModel(models.Model):

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

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

I can do this in forms to let the user choose date from datepicker.

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

这一年,我可以使用 CharField/IntegerFieldchoices 类似于在这个 SO 答案.

For year, I can use a CharField/IntegerField with choices similar to what has been done in this SO answer.

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 年,不会改变可用选项.

The problem, however, is that change of current year from say, 2018 to 2019, will not change the available options.

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

Can you help or provide hints to achieve what I want to do?

推荐答案

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

My initial thought was to write a callable that returns the choices, that will be evaluated for each request.

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 每年都会在选项更改时尝试创建迁移.

However this doesn't work, because Django's check framework doesn't allow the year_choices to be used as the default. Even if you could hack the choices to be generated dynamically, it would have the disadvantage that Django would try to create a migration each year when the choices change.

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

You can avoid this by generating the choices at the form level instead. You can use validators in the model to prevent invalid data. Note that MaxValueValidator is wrapped in a function max_value_current_year to avoid a new migration every 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)

这篇关于Django 中的年份字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆