views:

682

answers:

3

I've got a model where I need to store birth year. I'm using django admin. The person using this will be filling out loads of people every day, and DateField() shows too much (not interested in the day/month).

This is a mockup model showing how it is now:

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

As you can see, most of the people is 17 years old, so I'm getting their birth year as default.

Can I do this better? How can I make a YearField out of the DateField? If making a YearField I can maybe even make some "easy tags" like the "now" that date has. (Of course, a specialized BornYearField would have easy buttons for 1989, 1990, 1991 and other common years)

A: 

I don't agree with placing the default value in the model. You would be better off placing it in your template.

Fragsworth
Hmm. So, customizing the django-admin templates? I don't know how I would do that, since they are extremely generic and it's hard to just set that one field.
Velmont
OK, I found some documentation. Instead of placing it in the template, I can do it with a form, and setting the `initial` argument http://docs.djangoproject.com/en/dev/ref/forms/fields/#initial -- Looks clean and nice.
Velmont
+3  A: 

Also, and this isn't that relevant for your case, but is useful being aware of, don't use datetime.date.today(), or datetime.datetime.now() as defaults. This is executed once, when the server is started up.

You are much better off passing the callables in:

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

Note, you could use a lambda to make it relative:

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

Of course, this is naive, and assumes there have been 5 leap years in the past 17 years.

Matthew Schinckel
Yes, I knew that problem. However, I thought since this is a year field merely to help the people putting in new members all day, it only needs update once a year. It just needs to «almost hit» the avarage age. But thank you, of course a lambda solution is better.
Velmont
A: 

You can also do this:

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

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

I hope this will help you.

Oscar Carballal