772
772
Regroups a list of alike objects by a common attribute.
774
This complex tag is best illustrated by use of an example: say that ``people``
775
is a list of people represented by dictionaries with ``first_name``,
776
``last_name``, and ``gender`` keys:
774
This complex tag is best illustrated by way of an example: say that "places" is a list of cities represented by dictionaries containing ``"name"``, ``"population"``, and ``"country"`` keys:
778
776
.. code-block:: python
781
{'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},
782
{'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
783
{'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
784
{'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},
785
{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},
779
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
780
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
781
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
782
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
783
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
788
...and you'd like to display a hierarchical list that is ordered by gender,
805
You can use the ``{% regroup %}`` tag to group the list of people by gender.
786
...and you'd like to display a hierarchical list that is ordered by country, like this:
790
* Calcutta: 15,000,000
792
* New York: 20,000,000
798
You can use the ``{% regroup %}`` tag to group the list of cities by country.
806
799
The following snippet of template code would accomplish this::
808
{% regroup people by gender as gender_list %}
801
{% regroup cities by country as country_list %}
811
{% for gender in gender_list %}
812
<li>{{ gender.grouper }}
804
{% for country in country_list %}
805
<li>{{ country.grouper }}
814
{% for item in gender.list %}
815
<li>{{ item.first_name }} {{ item.last_name }}</li>
807
{% for item in country.list %}
808
<li>{{ item.name }}: {{ item.population }}</li>
822
815
Let's walk through this example. ``{% regroup %}`` takes three arguments: the
823
816
list you want to regroup, the attribute to group by, and the name of the
824
resulting list. Here, we're regrouping the ``people`` list by the ``gender``
825
attribute and calling the result ``gender_list``.
817
resulting list. Here, we're regrouping the ``cities`` list by the ``country``
818
attribute and calling the result ``country_list``.
827
``{% regroup %}`` produces a list (in this case, ``gender_list``) of
820
``{% regroup %}`` produces a list (in this case, ``country_list``) of
828
821
**group objects**. Each group object has two attributes:
830
* ``grouper`` -- the item that was grouped by (e.g., the string "Male" or
832
* ``list`` -- a list of all items in this group (e.g., a list of all people
823
* ``grouper`` -- the item that was grouped by (e.g., the string "India" or
825
* ``list`` -- a list of all items in this group (e.g., a list of all cities
826
with country='India').
835
828
Note that ``{% regroup %}`` does not order its input! Our example relies on
836
the fact that the ``people`` list was ordered by ``gender`` in the first place.
837
If the ``people`` list did *not* order its members by ``gender``, the
838
regrouping would naively display more than one group for a single gender. For
839
example, say the ``people`` list was set to this (note that the males are not
829
the fact that the ``cities`` list was ordered by ``country`` in the first place.
830
If the ``cities`` list did *not* order its members by ``country``, the
831
regrouping would naively display more than one group for a single country. For
832
example, say the ``cities`` list was set to this (note that the countries are not
840
833
grouped together):
842
835
.. code-block:: python
845
{'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
846
{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'},
847
{'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
848
{'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},
849
{'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},
838
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
839
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
840
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
841
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
842
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
852
With this input for ``people``, the example ``{% regroup %}`` template code
845
With this input for ``cities``, the example ``{% regroup %}`` template code
853
846
above would result in the following output:
851
* New York: 20,000,000
853
* Calcutta: 15,000,000
875
857
The easiest solution to this gotcha is to make sure in your view code that the
876
858
data is ordered according to how you want to display it.
878
860
Another solution is to sort the data in the template using the
879
861
:tfilter:`dictsort` filter, if your data is in a list of dictionaries::
881
{% regroup people|dictsort:"gender" by gender as gender_list %}
863
{% regroup cities|dictsort:"country" by country as country_list %}
884
865
Grouping on other properties
885
866
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
887
868
Any valid template lookup is a legal grouping attribute for the regroup
888
869
tag, including methods, attributes, dictionary keys and list items. For
889
example, if the "gender" field is a foreign key to a class with
870
example, if the "country" field is a foreign key to a class with
890
871
an attribute "description," you could use::
892
{% regroup people by gender.description as gender_list %}
873
{% regroup cities by country.description as country_list %}
894
Or, if ``gender`` is a field with ``choices``, it will have a
875
Or, if ``country`` is a field with ``choices``, it will have a
895
876
:meth:`^django.db.models.Model.get_FOO_display` method available as an
896
877
attribute, allowing you to group on the display string rather than the
897
878
``choices`` key::
899
{% regroup people by get_gender_display as gender_list %}
880
{% regroup cities by get_country_display as country_list %}
901
``{{ gender.grouper }}`` will now display the value fields from the
882
``{{ country.grouper }}`` will now display the value fields from the
902
883
``choices`` set rather than the keys.
904
885
.. templatetag:: spaceless