Django regroup
He fet quatre cosetes al programari del blog, per tal de mirar de passar al màxim la validació del w3c, encara tenc problemes amb els pre
que em genera el markdown dins paràgrefs i que no passen la validació, però al manco ara la plana es veu prou bé amb Konqueror.
Fent neteja m'he trobat amb la necessitat de refer la jerarquia de l'històric d'apunts. No era gens neta i com que ara el blog té un menú prou potent, he decidit posar molta cosa que estava al lateral com a opció del desplegable.
Per fer la jerarquia d'articles el que es ja el primer de tot és obtenir la llista d'arxius. Això ho feim cridant un tag creat ad-hoc pel blog
{% get_yearly_archive as archive_list %}
que el que fa és executar
Entry.objects.current_active().dates('pub_date', 'month', order='DESC')
i posar-ho a una variable que pot ser usada a la plantilla.
Amb aquest tag obtenim la llista de mesos en els que hi hem fet apunts. Un element d'aquest llista és per exemple:
datetime.datetime(2008, 2, 1, 0, 0)
Com podem veure és un tipus datetime
de python i com a tal podem obtenir-ne fàcilment l'any objecte.year
o el mes objecte.month
.
El que volem, com dic, és fer una jerarquia, és a dir, tenir una cosa com:
- 2009
- Abril 2009
- Març 2009
- 2008
- Desembre 2008
Això normalment duria força feina, però és aquí quan hom veu que Django està pensat per als reptes de la vida real, ja ve amb un template tag predefinit que ens permet fer agrupacions, el regroup
Donada una llista ordenada regroup ens crea una estructura de dades que contindrà els elements pels quals volem fer el grup i dins aquests els element de la llista que tenen aquest element.
En el nostre cas hem posat l'historial dins una variable anomenada archive_list
, que recordem és una llista de datetime
. Farem
{% regroup archive_list by year as historial_list %}
Amb això hem creat la nostra estructura de dades. Fixem-nos que l'exemple que duu la documentació de Django diu que regroup té com a paràmetre una llista de diccionaris. És part de la gràcia del tipat feble, pel que fa al funcionament de la funció l'estructura datetime
es comporta com espera l'iterador groupby
que és el que fa servir internament.
Podem simular-ho perfectament a la consola de iPython
>In [43]: p = itertools.groupby (x, lambda z: z.year)
>In [44]: for i in p:
> ....: print i[0]
> ....: for j in i[1]:
> ....: print j
Ja tenim l'estructura de dades, així que ara sols quedar recorre i presentar la informació tal com la volem. Per això cal tenir en compte que la nostra estructura defineix la variable grouper
que fa referència al valor del camp pel qual estam fent l'agrupació
{% for year in historial_list %}
<li>
<span class="dir">{{year.grouper }}</span>
<ul>
{% for d in year.list %}
<li>
<a href="{% setting "BLOG_ROOT" %} {{ year.grouper }}/{{d|date:"m" }}/'class="menu_content">
{{ d|date:"M Y" }}
</a>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
Com és habitual, és més llarg d'explicar que de fer.