Smart Loop List Creation in Python for Django Choice fields
So. The following isn't very 'smart' ;)
MONTHS = (
('Jan', 'Jan'),
('Feb', 'Feb'),
('Mar', 'Mar'),
('Apr', 'Apr'),
('May', 'May'),
('Jun', 'Jun'),
('Jul', 'Jul'),
('Aug', 'Aug'),
('Sep', 'Sep'),
('Oct', 'Oct'),
('Nov', 'Nov'),
('Dec', 'Dec'),
)
YEARS = (
('1995', '1995'),
开发者_如何学Go ('1996', '1996'),
('1997', '1997'),
('1998', '1998'),
('1999', '1999'),
('2000', '2000'),
('2001', '2001'),
('2002', '2002'),
('2003', '2003'),
('2004', '2004'),
('2005', '2005'),
('2006', '2006'),
('2007', '2007'),
('2008', '2008'),
('2009', '2009'),
('2010', '2010'),
)
I'm newer to python, and would love to produce stuff like this 'pythonically'.
Such as,
- a list of year tuples from 1995 to current year.
- a list of the abbreviated months of the year
Thanks Stackers'
In [17]: from datetime import datetime
In [18]: tuple((str(n), str(n)) for n in range(1995, datetime.now().year + 1))
Out[18]:
(('1995', '1995'),
('1996', '1996'),
('1997', '1997'),
('1998', '1998'),
('1999', '1999'),
('2000', '2000'),
('2001', '2001'),
('2002', '2002'),
('2003', '2003'),
('2004', '2004'),
('2005', '2005'),
('2006', '2006'),
('2007', '2007'),
('2008', '2008'),
('2009', '2009'),
('2010', '2010'))
In [19]: import calendar
In [20]: tuple((m, m) for m in calendar.month_abbr[1:])
Out[20]:
(('Jan', 'Jan'),
('Feb', 'Feb'),
('Mar', 'Mar'),
('Apr', 'Apr'),
('May', 'May'),
('Jun', 'Jun'),
('Jul', 'Jul'),
('Aug', 'Aug'),
('Sep', 'Sep'),
('Oct', 'Oct'),
('Nov', 'Nov'),
('Dec', 'Dec'))
Try using zip()
to make a list of two-tuples.
MONTHS = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
somemonth = models.TextField(max_length=3, choices=zip(MONTHS,MONTHS))
choices
will be set to [('Jan', 'Jan'), ('Feb', 'Feb'), ...]
.
In response to the comments on this answer, the "tuple" list comprehension version would be:
tuple((m, m) for m in MONTHS)
Versus the zip version:
tuple(zip(MONTHS, MONTHS))
But strictly speaking, Django doesn't need a tuple of choices, so:
zip(MONTHS, MONTHS)
See module time.
>>> import time
For the months we can use strptime
to turn a month number 1-12 into a struct_time
, and then use strftime
to pull the month name out.
>>> [time.strftime('%b', time.strptime(str(i), '%m')) for i in range(1, 13)]
['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
The years are more straightforward, we just need to know the current year (plus one, due to the way range
works).
>>> [str(i) for i in range(1995, time.localtime().tm_year + 1)]
['1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010']
I added str(i)
to have the years returned as strings since that's the way you wrote them. If integers are okay then you can drop the whole list comprehension and simply use range(...)
.
import datetime
from django.db import models
from django.utils.dates import MONTHS
class MyCoolModel(models.Model):
YEARS = YEARS = [(i,)*2 for i in range(1995, datetime.today().year + 1)]
month = models.PositiveSmallIntegerField(choices=MONTHS.items())
year = models.PositiveIntegerField(choices=YEARS)
Although some of the other answers might be "smarter", I dislike the idea of using a loop to define a tuple. Perhaps the following is a more readable compromise :
MONTHS = ( ('Jan',) * 2, ('Feb',) * 2, ('Mar',) * 2, ('Apr',) * 2, ('May',) * 2, ('Jun',) * 2, ('Jul',) * 2, ('Aug',) * 2, ('Sep',) * 2, ('Oct',) * 2, ('Nov',) * 2, ('Dec',) * 2, ) YEARS = ( ('1995',) * 2, ('1996',) * 2, ('1997',) * 2, ('1998',) * 2, ('1999',) * 2, ('2000',) * 2, ('2001',) * 2, ('2002',) * 2, ('2003',) * 2, ('2004',) * 2, ('2005',) * 2, ('2006',) * 2, ('2007',) * 2, ('2008',) * 2, ('2009',) * 2, ('2010',) * 2, )
精彩评论