Django的年场

问题描述 投票:6回答:3

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

class MyModel(models.Model):

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

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

    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年,当前年度的变化不会改变现有的选择。

你能帮忙或提供一些提示来实现我想做的事吗?

python django django-models
3个回答
10
投票

我最初的想法是编写一个返回选项的callable,它将针对每个请求进行评估。

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中,以避免每年进行新的迁移。

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)

import datetime

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)

2
投票

您可以使用IntegerField min_value和max_value将选项(年)放在表单中。在模型中,您可以使用IntegerField而无需选择。

因此,您不必担心年份何时发生变化,因为您只会更改表单中的选项。

如果你想自动更改年份,这可以帮助你:Django forms integerField set max_value on runtime


1
投票

对于那些不喜欢长期选择领域的人,即在@Alasdair解决方案中,想象一下从1984年到2019年的选择领域,这么长的选择列表。如果有一个字段,你可以键入年份,仍然有办法增加或减少。为了解决这个问题,请使用带有MinValueValidator和MaxValueValidator的models.PositiveIntegerField,如下所示:

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])
© www.soinside.com 2019 - 2024. All rights reserved.