2009-10-04 11 views
23

Ho un modello in cui ho bisogno di archiviare l'anno di nascita. Sto usando l'admin di django. La persona che utilizza questo riempirà un sacco di persone ogni giorno e DateField() mostra troppo (non interessa il giorno/mese).Solo mostrando anno in admin django, un YearField invece di DateField?

Questo è un modello mockup mostrando come è ora:

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

Come potete vedere, la maggior parte delle persone è di 17 anni, quindi mi sto loro anno di nascita come predefinito.

Posso fare meglio? Come posso creare un YearField dal DateField? Se faccio un YearField posso forse persino fare alcuni "tag facili" come "ora" che ha questa data. (Naturalmente, un BornYearField specializzato avrebbe pulsanti facili per 1989, 1990, 1991 e altri anni comuni)

risposta

9

Inoltre, e questo non è rilevante per il tuo caso, ma è utile essere a conoscenza, non usare datetime.date.today(), o datetime.datetime.now() come valori predefiniti. Questo viene eseguito una volta, quando il server viene avviato.

Tu sei molto meglio passando i callable in:

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

nota, è possibile utilizzare un lambda per renderlo relativo:

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

Naturalmente, questo è ingenuo, ed assume lì sono stati 5 anni bisestili negli ultimi 17 anni.

+0

Sì, lo sapevo. Tuttavia, ho pensato che dal momento che questo è un campo di un anno solo per aiutare le persone a mettere nuovi membri tutto il giorno, ha bisogno solo di aggiornamento una volta all'anno. Ha solo bisogno di "quasi colpire" l'età media. Ma grazie, ovviamente una soluzione lambda è migliore. –

+9

Sono solo io o questa risposta in up non riguarda la domanda? –

6

Si può anche fare questo:

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) 

Spero che questo vi aiuterà.

+0

Django ignora 'max_length' per' IntegerField', e ti avviserà in Django 1.8+. Vedi [this] (http://stackoverflow.com/questions/30849862/django-max-length-for-integerfield) per ulteriori informazioni. – freethebees

+1

Il tuo primo elemento tupla YEARS dovrebbe essere un numero intero in quanto il tipo di data di nascita è Campo intero. Potresti usare una comprensione delle liste qui per costruire le scelte e avere una dichiarazione abbastanza semplice. –

21

ho trovato this solution che risolve il tutto abbastanza elegantemente penso (non il mio codice):

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) 

Modificare l'inizio gamma di estendere l'elenco :-)

+11

Si potrebbe tutto su una riga: 'YEAR_CHOICES = [(r, r) per r nell'intervallo (1984, datetime.date.today(). Year + 1)]' – Bobort

+0

il valore predefinito dovrebbe probabilmente assomigliare a 'default = lambda: datetime.datetime.now().anno 'altrimenti aggiornerà il valore predefinito al riavvio del servizio – askvictor

+1

Inoltre, se vuoi che le migrazioni funzionino, non puoi usare un lambda, quindi dovresti definire una funzione semplice 'def current_year():. ..' e usa quello (senza parentesi) invece 'default = current_year' – askvictor

2

Per una soluzione non prevedono Modello scelte:

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

che sarà anche creare un segnaposto nel campo di input con il valore della help_text.