2009-10-04 48 views
23

Tengo un modelo donde necesito almacenar el año de nacimiento. Estoy usando django admin. La persona que usa esto estará llenando muchas personas todos los días, y DateField() muestra demasiado (no está interesado en el día/mes).¿Solo se muestra el año en django admin, un YearField en lugar de DateField?

Este es un modelo maqueta mostrando cómo es ahora:

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

Como se puede ver, la mayoría de las personas es de 17 años, así que estoy poniendo su año de nacimiento como predeterminado.

¿Puedo hacer esto mejor? ¿Cómo puedo hacer un Yearfield de DateField? Si hago un YearField, puedo incluso hacer algunas "etiquetas fáciles" como el "ahora" que tiene esa fecha. (Por supuesto, un BornYearField especializado tendría botones fáciles para 1989, 1990, 1991 y otros años comunes)

Respuesta

9

Además, y esto no es tan relevante para su caso, pero es útil conocerlo, no utilizar datetime.date.today(), o datetime.datetime.now() como valores predeterminados. Esto se ejecuta una vez, cuando el servidor se inicia.

usted es mucho mejor pasar los callables en:

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

Nota, se puede utilizar una lambda para que sea relativa:

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

Por supuesto, esto es ingenuo, y asume que hay han sido 5 años bisiestos en los últimos 17 años.

+0

Sí, sabía el problema. Sin embargo, pensé que dado que este es un campo de un año simplemente para ayudar a la gente a incluir nuevos miembros todo el día, solo necesita actualizarse una vez al año. Solo necesita "casi golpear" la edad promedio. Pero gracias, por supuesto, una solución lambda es mejor. –

+9

¿Es solo yo o esta respuesta votada no se trata de la pregunta? –

6

También puede hacer esto:

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) 

espero que esto le ayudará.

+0

Django ignora 'max_length' para' IntegerField', y te advertirá en Django 1.8+. Ver [this] (http://stackoverflow.com/questions/30849862/django-max-length-for-integerfield) para más. – freethebees

+1

El primer elemento de la tupla AÑOS debe ser un número entero, ya que el tipo de fecha de nacimiento es IntegerField. Puede usar una lista de comprensión aquí para construir las opciones y tener una declaración bastante simple. –

21

He encontrado this solution que resuelve todo el asunto muy elegantemente creo (no es mi código):

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) 

Editar el inicio del rango de ampliar la lista :-)

+11

Puede todo en una línea: 'YEAR_CHOICES = [(r, r) para r en rango (1984, datetime.date.today(). Year + 1)]' – Bobort

+0

el valor predeterminado probablemente debería parecerse a 'default = lambda: datetime.datetime.now().year' de lo contrario solo actualizará el valor predeterminado cuando se reinicie el servicio – askvictor

+1

Además, si desea que las migraciones funcionen, no podrá usar una lambda, por lo que deberá definir una función simple 'def current_year():. ..' y usa eso (sin paréntesis) en su lugar 'default = current_year' – askvictor

2

Para una solución que no implique Modelo opciones:

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>") 

Eso también va a crear un marcador de posición en el campo de entrada con el valor de help_text.

Cuestiones relacionadas