Improved docs/templates.txt section on the 'regroup' tag

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5710 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-07-15 21:16:32 +00:00
parent 2a500b3551
commit 0d9f21bb75
1 changed files with 72 additions and 22 deletions

View File

@ -741,8 +741,19 @@ regroup
Regroup a list of alike objects by a common attribute. Regroup a list of alike objects by a common attribute.
This complex tag is best illustrated by use of an example: say that ``people`` This complex tag is best illustrated by use of an example: say that ``people``
is a list of ``Person`` objects that have ``first_name``, ``last_name``, and is a list of people represented by dictionaries with ``first_name``,
``gender`` attributes, and you'd like to display a list that looks like: ``last_name``, and ``gender`` keys::
people = [
{'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},
{'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
{'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
{'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},
{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},
]
...and you'd like to display a hierarchical list that is ordered by gender,
like this:
* Male: * Male:
* George Bush * George Bush
@ -753,33 +764,72 @@ is a list of ``Person`` objects that have ``first_name``, ``last_name``, and
* Unknown: * Unknown:
* Pat Smith * Pat Smith
The following snippet of template code would accomplish this dubious task:: You can use the ``{% regroup %}`` tag to group the list of people by gender.
The following snippet of template code would accomplish this::
{% regroup people by gender as gender_list %}
{% regroup people by gender as grouped %}
<ul> <ul>
{% for group in grouped %} {% for gender in gender_list %}
<li>{{ group.grouper }} <li>{{ gender.grouper }}
<ul> <ul>
{% for item in group.list %} {% for item in gender.list %}
<li>{{ item }}</li> <li>{{ item.first_name }} {{ item.last_name }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
As you can see, ``{% regroup %}`` populates a variable with a list of objects Let's walk through this example. ``{% regroup %}`` takes three arguments: the
with ``grouper`` and ``list`` attributes. ``grouper`` contains the item that list you want to regroup, the attribute to group by, and the name of the
was grouped by; ``list`` contains the list of objects that share that resulting list. Here, we're regrouping the ``people`` list by the ``gender``
``grouper``. In this case, ``grouper`` would be ``Male``, ``Female`` and attribute and calling the result ``gender_list``.
``Unknown``, and ``list`` is the list of people with those genders.
Note that ``{% regroup %}`` does not work when the list to be grouped is not ``{% regroup %}`` produces a list (in this case, ``gender_list``) of
sorted by the key you are grouping by! This means that if your list of people **group objects**. Each group object has two attributes:
was not sorted by gender, you'd need to make sure it is sorted before using it,
i.e.::
{% regroup people|dictsort:"gender" by gender as grouped %} * ``grouper`` -- the item that was grouped by (e.g., the string "Male" or
"Female").
* ``list`` -- a list of all items in this group (e.g., a list of all people
with gender='Male').
Note that ``{% regroup %}`` does not order its input! Our example relies on
the fact that the ``people`` list was ordered by ``gender`` in the first place.
If the ``people`` list did *not* order its members by ``gender``, the regrouping
would naively display more than one group for a single gender. For example,
say the ``people`` list was set to this (note that the males are not grouped
together)::
people = [
{'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},
{'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
{'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},
{'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},
]
With this input for ``people``, the example ``{% regroup %}`` template code
above would result in the following output:
* Male:
* Bill Clinton
* Unknown:
* Pat Smith
* Female:
* Margaret Thatcher
* Male:
* George Bush
* Female:
* Condoleezza Rice
The easiest solution to this gotcha is to make sure in your view code that the
data is ordered according to how you want to display it.
Another solution is to sort the data in the template using the ``dictsort``
filter, if your data is in a list of dictionaries::
{% regroup people|dictsort:"gender" by gender as gender_list %}
spaceless spaceless
~~~~~~~~~ ~~~~~~~~~
@ -965,14 +1015,14 @@ If value is ``None``, use given default.
dictsort dictsort
~~~~~~~~ ~~~~~~~~
Takes a list of dicts, returns that list sorted by the property given in the Takes a list of dictionaries, returns that list sorted by the key given in
argument. the argument.
dictsortreversed dictsortreversed
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Takes a list of dicts, returns that list sorted in reverse order by the Takes a list of dictionaries, returns that list sorted in reverse order by the
property given in the argument. key given in the argument.
divisibleby divisibleby
~~~~~~~~~~~ ~~~~~~~~~~~