Показывать только год в админке django, а YearField вместо DateField? - PullRequest
28 голосов
/ 05 октября 2009

У меня есть модель, где мне нужно хранить год рождения. Я использую админку 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 и других обычных лет)

Ответы [ 4 ]

26 голосов
/ 09 июля 2014

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

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

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

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

9 голосов
/ 06 октября 2009

Кроме того, и это не так важно для вашего случая, но полезно знать, что не используйте 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 високосных лет.

6 голосов
/ 18 сентября 2010

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

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 голосов
/ 12 августа 2017

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

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.

...