2009-10-04 3 views
23

J'ai un modèle où je dois stocker l'année de naissance. J'utilise l'admin django. La personne qui utilise cela va remplir des tas de gens chaque jour, et DateField() montre trop (pas intéressé par le jour/mois).Afficher seulement l'année dans l'admin django, un YearField au lieu de DateField?

Ce modèle mockup montrant comment il est maintenant:

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

Comme vous pouvez le voir, la plupart des gens est de 17 ans, donc je suis obtenir leur année de naissance par défaut.

Puis-je faire mieux? Comment puis-je faire un YearField hors de DateField? Si je fais un YearField, je peux peut-être même faire des "tags faciles" comme le "maintenant" que cette date a. (Bien sûr, un BornYearField spécialisé aurait des boutons faciles pour 1989, 1990, 1991 et d'autres années communes)

Répondre

9

Aussi, et ce n'est pas pertinent pour votre cas, mais est utile étant conscient de, ne pas utiliser datetime.date.today() ou datetime.datetime.now() en tant que valeurs par défaut. Ceci est exécuté une fois, lorsque le serveur est démarré.

Vous êtes beaucoup mieux passer les appelables dans:

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

Remarque, vous pouvez utiliser un lambda pour faire rapport:

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

Bien sûr, cela est naïf, et suppose qu'il ont été 5 années bissextiles au cours des 17 dernières années.

+0

Oui, je connaissais ce problème. Cependant, j'ai pensé que puisque c'est un champ d'année simplement pour aider les gens à mettre de nouveaux membres toute la journée, il suffit de mettre à jour une fois par an. Il suffit de «presque atteindre» l'âge moyen. Mais merci, bien sûr, une solution lambda est meilleure. –

+9

Est-ce juste moi ou cette réponse mise à jour n'est pas à propos de la question? –

6

Vous pouvez aussi le faire:

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) 

J'espère que cela vous aidera.

+0

Django ignore 'max_length' pour' IntegerField', et vous avertira dans Django 1.8+. Voir [this] (http://stackoverflow.com/questions/30849862/django-max-length-for-integerfield) pour plus d'informations. – freethebees

+1

Votre premier élément TUYAU YEARS doit être un entier lorsque le type de date de naissance est IntegerField. Vous pouvez utiliser une liste de compréhension ici pour construire les choix et avoir une déclaration assez simple. –

21

Je trouve this solution qui résout élégamment je pense tout à fait la chose (pas mon code):

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) 

Modifier le début de la plage pour étendre la liste :-)

+11

Vous pouvez tout sur une ligne: 'YEAR_CHOICES = [(r, r) pour r dans la plage (1984, datetime.date.today(). Year + 1)]' – Bobort

+0

la valeur par défaut devrait probablement ressembler 'default = lambda: datetime.datetime.now().année' sinon elle ne mettra à jour que le défaut lors du redémarrage du service – askvictor

+1

Aussi, si vous voulez que les migrations fonctionnent, alors vous ne pouvez pas utiliser un lambda, vous devez donc définir une fonction simple 'def current_year():. ..' et utilisez cela (sans les parenthèses) à la place 'default = current_year' – askvictor

2

Pour une solution ne comportant pas de modèle choix:

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

Cela va également créer un espace réservé dans le champ de saisie avec la valeur de help_text.

Questions connexes