views:

211

answers:

2

I have an Article model which has a date field. I want to query against all Article objects, and have a datatype returned with each distinct year, and then each distinct month within that.

for instance

archives = { 2009: {12, [, , ...], 11: [...]}, 2008: {12, [...], 11: [...]}, }

is this possible?

A: 

There is no quick solution, but you may check dates() method.

Dmitry Shevchenko
For example, if you want it for month, `[(date, Model.objects.filter(pub_date__year=date.year, pub_date__month=date.month)) for date in Model.objects.dates('pub_date', 'month')]` will get you a list of `(date, QuerySet)` tuples for every month (assuming your field is named `pub_date`).
LeafStorm
+1  A: 

This sort of question seems to come up fairly often. The easiest solution is to loop through the data and group the objects by year and month. You can do this by hand in the view or using regroup in your template. It really depends on what you want to do with the data.

If grouping Archives by year and month is a very common thing for you to do in your application, you might want to consider creating a year and month field that you populate on save().

By hand it could be something like this:

arch = {}
for a in Archive.objects.all():
    year = arch.get(a.pub_date.year, {})
    month = year.get(a.pub_date.month, [])
    month.append(a)
    year[a.pub_date.month] = month
    arch[a.pub_date.year] = year

Or pushing all the grouping logic into the template using regroup (untested):

{% regroup archives by pub_date.year as year_list %}
{% for year in year_list %}
  Year: {{ year.grouper }}
  {% regroup year.list by pub_date.month as month_list %}
  {% for month in month_list %}
    Month: {{ month.grouper }}
    {% for archive in month.list %}
      {{ archive }}
    {% endfor %}
  {% endfor %}
{% endfor %}

I would personally try to put the logic in the view instead of in the template.

Here are a few related posts:

istruble