Подтвердить что ты не робот

Только показ года в django admin, YearField вместо DateField?

У меня есть модель, где мне нужно хранить год рождения. Я использую администратор django. Человек, использующий это, будет заполнять множество людей каждый день, а DateField() показывает слишком много (не интересует день/месяц).

Это модель макета, показывающая, как она теперь:

class Person(models.Model):
  name = models.CharField(max_length=256)
  born = models.IntegerField(default=lambda: date.today().year - 17)

Как вы можете видеть, большинству людей исполнилось 17 лет, поэтому я получаю их год рождения по умолчанию.

Могу ли я сделать это лучше? Как я могу сделать YearField из DateField? Если вы создаете YearField, я могу даже сделать некоторые "легкие теги", подобные "сейчас", которые есть у этой даты. (Конечно, у специализированного BornYearField были бы простые кнопки для 1989, 1990, 1991 и других общих лет).

4b9b3361

Ответ 1

Я нашел это решение, которое решает все это довольно элегантно, я думаю (не мой код):

import datetime
YEAR_CHOICES = []
for r in range(1980, (datetime.datetime.now().year+1)):
    YEAR_CHOICES.append((r,r))

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

Отредактируйте начало диапазона, чтобы расширить список:-)

Ответ 2

Кроме того, и это не относится к вашему делу, но полезно знать, не используйте datetime.date.today() или datetime.datetime.now() как значения по умолчанию. Это выполняется один раз, когда сервер запущен.

Вы намного лучше передаете вызывающие файлы в:

date = models.DateField(default=datetime.date.today)

Заметьте, вы можете использовать лямбда, чтобы сделать ее относительной:

date = models.DateField(default=lambda : datetime.date.today() - datetime.timedelta(days=6210))

Конечно, это наивно и предполагает, что за последние 17 лет было 5 високосных годов.

Ответ 3

Вы также можете сделать это:

YEARS = (
    ("1990", "1990"),
    ("1991", "1991"),
    ("1992", "1992"),
    # P.e. generate a list from 1960 to date.today().year
    # The reason why they choice key and text value are the
    # same is that if you generate from 1960 to 2060 it will collide.
    #
    # E.g
    # from datetime import datetime
    # def tuplify(x): return (x,x)   # str(x) if needed
    # current_year = datetime.now().year
    # YEARS = map(tuplify, range(1930, current_year + 1))  # range(1,4) gives [1,2,3]
)

class Whatever(models.Model):
    # Show a list with years
    birthdate = models.IntegerField(max_length=2, choices=YEARS)

Надеюсь, это поможет вам.

Ответ 4

Для решения, не связанного с выбором модели:

from django.core.validators import MinValueValidator, MaxValueValidator

class Person(models.Model):
    year = models.PositiveIntegerField(
            validators=[
                MinValueValidator(1900), 
                MaxValueValidator(datetime.now().year)],
            help_text="Use the following format: <YYYY>")

Это также создаст местозаполнитель в поле ввода со значением help_text.