Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

625
Visualizações
Year Field in 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'}))

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)

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?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

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)

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.

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)
over 4 years ago · Santiago Trujillo Relatório

0

You can put the options(years) in the form, using the IntegerField min_value and max_value. In model you can use the IntegerField without choices.

  • Forms: IntegerField
  • More about forms

So, you won't worry about when the year change, because you will only change the options in the form.

If you want to change the year automatically, this could help you: Django forms integerField set max_value on runtime

over 4 years ago · Santiago Trujillo Relatório

0

For those who don't prefer having long choice fields i.e. in @Alasdair solution imagine having a choice field from 1984 to 2019, such a long choice list. How about having a field you can type the year and still have a way to increment or decrements. To solve this my way, use models.PositiveIntegerField with MinValueValidator and MaxValueValidator as shown below:

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])
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda