summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreya Bamne <shreya.bamne@gmail.com>2021-11-17 12:01:34 +0100
committerCarlton Gibson <carlton@noumenal.es>2021-11-18 14:01:04 +0100
commite53aea2e23b592c4774f0e9fa7f9f9d726a40dfc (patch)
treed0163c1f61e7caa1de1dea5451ec2679d886239a
parent1fe23bdd29a8f2f6802c2038702ff7a5d0e21a0d (diff)
Refs #19721 -- Moved ModelAdmin.list_filter docs into a separate file.
Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
-rw-r--r--docs/ref/contrib/admin/filters.txt193
-rw-r--r--docs/ref/contrib/admin/index.txt157
2 files changed, 198 insertions, 152 deletions
diff --git a/docs/ref/contrib/admin/filters.txt b/docs/ref/contrib/admin/filters.txt
new file mode 100644
index 0000000000..a0cd931ce4
--- /dev/null
+++ b/docs/ref/contrib/admin/filters.txt
@@ -0,0 +1,193 @@
+.. _modeladmin-list-filters:
+
+===========================
+``ModelAdmin`` List Filters
+===========================
+
+.. currentmodule:: django.contrib.admin
+
+``ModelAdmin`` classes can define list filters that appear in the right sidebar
+of the change list page of the admin, as illustrated in the following
+screenshot:
+
+.. image:: _images/list_filter.png
+
+To activate per-field filtering, set :attr:`ModelAdmin.list_filter` to a list
+or tuple of elements, where each element is one of the following types:
+
+- A field name.
+- A subclass of ``django.contrib.admin.SimpleListFilter``.
+- A 2-tuple containing a field name and a subclass of
+ ``django.contrib.admin.FieldListFilter``.
+
+See the examples below for discussion of each of these options for defining
+``list_filter``.
+
+Using a field name
+==================
+
+The simplest option is to specify the required field names from your model.
+
+Each specified field should be either a ``BooleanField``, ``CharField``,
+``DateField``, ``DateTimeField``, ``IntegerField``, ``ForeignKey`` or
+``ManyToManyField``, for example::
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_filter = ('is_staff', 'company')
+
+Field names in ``list_filter`` can also span relations
+using the ``__`` lookup, for example::
+
+ class PersonAdmin(admin.UserAdmin):
+ list_filter = ('company__name',)
+
+Using a ``SimpleListFilter``
+============================
+
+For custom filtering, you can define your own list filter by subclassing
+``django.contrib.admin.SimpleListFilter``. You need to provide the ``title``
+and ``parameter_name`` attributes, and override the ``lookups`` and
+``queryset`` methods, e.g.::
+
+ from datetime import date
+
+ from django.contrib import admin
+ from django.utils.translation import gettext_lazy as _
+
+ class DecadeBornListFilter(admin.SimpleListFilter):
+ # Human-readable title which will be displayed in the
+ # right admin sidebar just above the filter options.
+ title = _('decade born')
+
+ # Parameter for the filter that will be used in the URL query.
+ parameter_name = 'decade'
+
+ def lookups(self, request, model_admin):
+ """
+ Returns a list of tuples. The first element in each
+ tuple is the coded value for the option that will
+ appear in the URL query. The second element is the
+ human-readable name for the option that will appear
+ in the right sidebar.
+ """
+ return (
+ ('80s', _('in the eighties')),
+ ('90s', _('in the nineties')),
+ )
+
+ def queryset(self, request, queryset):
+ """
+ Returns the filtered queryset based on the value
+ provided in the query string and retrievable via
+ `self.value()`.
+ """
+ # Compare the requested value (either '80s' or '90s')
+ # to decide how to filter the queryset.
+ if self.value() == '80s':
+ return queryset.filter(
+ birthday__gte=date(1980, 1, 1),
+ birthday__lte=date(1989, 12, 31),
+ )
+ if self.value() == '90s':
+ return queryset.filter(
+ birthday__gte=date(1990, 1, 1),
+ birthday__lte=date(1999, 12, 31),
+ )
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_filter = (DecadeBornListFilter,)
+
+.. note::
+
+ As a convenience, the ``HttpRequest`` object is passed to the ``lookups``
+ and ``queryset`` methods, for example::
+
+ class AuthDecadeBornListFilter(DecadeBornListFilter):
+
+ def lookups(self, request, model_admin):
+ if request.user.is_superuser:
+ return super().lookups(request, model_admin)
+
+ def queryset(self, request, queryset):
+ if request.user.is_superuser:
+ return super().queryset(request, queryset)
+
+ Also as a convenience, the ``ModelAdmin`` object is passed to the
+ ``lookups`` method, for example if you want to base the lookups on the
+ available data::
+
+ class AdvancedDecadeBornListFilter(DecadeBornListFilter):
+
+ def lookups(self, request, model_admin):
+ """
+ Only show the lookups if there actually is
+ anyone born in the corresponding decades.
+ """
+ qs = model_admin.get_queryset(request)
+ if qs.filter(
+ birthday__gte=date(1980, 1, 1),
+ birthday__lte=date(1989, 12, 31),
+ ).exists():
+ yield ('80s', _('in the eighties'))
+ if qs.filter(
+ birthday__gte=date(1990, 1, 1),
+ birthday__lte=date(1999, 12, 31),
+ ).exists():
+ yield ('90s', _('in the nineties'))
+
+Using a field name and an explicit ``FieldListFilter``
+======================================================
+
+Finally, if you wish to specify an explicit filter type to use with a field you
+may provide a ``list_filter`` item as a 2-tuple, where the first element is a
+field name and the second element is a class inheriting from
+``django.contrib.admin.FieldListFilter``, for example::
+
+ class PersonAdmin(admin.ModelAdmin):
+ list_filter = (
+ ('is_staff', admin.BooleanFieldListFilter),
+ )
+
+Here the ``is_staff`` field will use the ``BooleanFieldListFilter``. Specifying
+only the field name, fields will automatically use the appropriate filter for
+most cases, but this format allows you to control the filter used.
+
+The following examples show available filter classes that you need to opt-in
+to use.
+
+You can limit the choices of a related model to the objects involved in
+that relation using ``RelatedOnlyFieldListFilter``::
+
+ class BookAdmin(admin.ModelAdmin):
+ list_filter = (
+ ('author', admin.RelatedOnlyFieldListFilter),
+ )
+
+Assuming ``author`` is a ``ForeignKey`` to a ``User`` model, this will
+limit the ``list_filter`` choices to the users who have written a book,
+instead of listing all users.
+
+You can filter empty values using ``EmptyFieldListFilter``, which can
+filter on both empty strings and nulls, depending on what the field
+allows to store::
+
+ class BookAdmin(admin.ModelAdmin):
+ list_filter = (
+ ('title', admin.EmptyFieldListFilter),
+ )
+
+.. note::
+
+ The :class:`~django.contrib.contenttypes.fields.GenericForeignKey` field is
+ not supported.
+
+List filters typically appear only if the filter has more than one choice. A
+filter's ``has_output()`` method controls whether or not it appears.
+
+It is possible to specify a custom template for rendering a list filter::
+
+ class FilterWithCustomTemplate(admin.SimpleListFilter):
+ template = "custom_template.html"
+
+See the default template provided by Django (``admin/filter.html``) for a
+concrete example.
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index 0f427c06f0..5caea603c1 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -66,6 +66,7 @@ Other topics
:maxdepth: 1
actions
+ filters
admindocs
javascript
@@ -853,159 +854,11 @@ subclass::
.. attribute:: ModelAdmin.list_filter
Set ``list_filter`` to activate filters in the right sidebar of the change
- list page of the admin, as illustrated in the following screenshot:
-
- .. image:: _images/list_filter.png
-
- ``list_filter`` should be a list or tuple of elements, where each element
- should be of one of the following types:
-
- * a field name, where the specified field should be either a
- ``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``,
- ``IntegerField``, ``ForeignKey`` or ``ManyToManyField``, for example::
-
- class PersonAdmin(admin.ModelAdmin):
- list_filter = ('is_staff', 'company')
-
- Field names in ``list_filter`` can also span relations
- using the ``__`` lookup, for example::
-
- class PersonAdmin(admin.UserAdmin):
- list_filter = ('company__name',)
-
- * a class inheriting from ``django.contrib.admin.SimpleListFilter``,
- which you need to provide the ``title`` and ``parameter_name``
- attributes to and override the ``lookups`` and ``queryset`` methods,
- e.g.::
-
- from datetime import date
-
- from django.contrib import admin
- from django.utils.translation import gettext_lazy as _
-
- class DecadeBornListFilter(admin.SimpleListFilter):
- # Human-readable title which will be displayed in the
- # right admin sidebar just above the filter options.
- title = _('decade born')
-
- # Parameter for the filter that will be used in the URL query.
- parameter_name = 'decade'
-
- def lookups(self, request, model_admin):
- """
- Returns a list of tuples. The first element in each
- tuple is the coded value for the option that will
- appear in the URL query. The second element is the
- human-readable name for the option that will appear
- in the right sidebar.
- """
- return (
- ('80s', _('in the eighties')),
- ('90s', _('in the nineties')),
- )
-
- def queryset(self, request, queryset):
- """
- Returns the filtered queryset based on the value
- provided in the query string and retrievable via
- `self.value()`.
- """
- # Compare the requested value (either '80s' or '90s')
- # to decide how to filter the queryset.
- if self.value() == '80s':
- return queryset.filter(birthday__gte=date(1980, 1, 1),
- birthday__lte=date(1989, 12, 31))
- if self.value() == '90s':
- return queryset.filter(birthday__gte=date(1990, 1, 1),
- birthday__lte=date(1999, 12, 31))
-
- class PersonAdmin(admin.ModelAdmin):
- list_filter = (DecadeBornListFilter,)
-
- .. note::
-
- As a convenience, the ``HttpRequest`` object is passed to the
- ``lookups`` and ``queryset`` methods, for example::
-
- class AuthDecadeBornListFilter(DecadeBornListFilter):
-
- def lookups(self, request, model_admin):
- if request.user.is_superuser:
- return super().lookups(request, model_admin)
-
- def queryset(self, request, queryset):
- if request.user.is_superuser:
- return super().queryset(request, queryset)
-
- Also as a convenience, the ``ModelAdmin`` object is passed to
- the ``lookups`` method, for example if you want to base the
- lookups on the available data::
-
- class AdvancedDecadeBornListFilter(DecadeBornListFilter):
-
- def lookups(self, request, model_admin):
- """
- Only show the lookups if there actually is
- anyone born in the corresponding decades.
- """
- qs = model_admin.get_queryset(request)
- if qs.filter(birthday__gte=date(1980, 1, 1),
- birthday__lte=date(1989, 12, 31)).exists():
- yield ('80s', _('in the eighties'))
- if qs.filter(birthday__gte=date(1990, 1, 1),
- birthday__lte=date(1999, 12, 31)).exists():
- yield ('90s', _('in the nineties'))
-
- * a tuple, where the first element is a field name and the second
- element is a class inheriting from
- ``django.contrib.admin.FieldListFilter``, for example::
-
- class PersonAdmin(admin.ModelAdmin):
- list_filter = (
- ('is_staff', admin.BooleanFieldListFilter),
- )
-
- You can limit the choices of a related model to the objects involved in
- that relation using ``RelatedOnlyFieldListFilter``::
-
- class BookAdmin(admin.ModelAdmin):
- list_filter = (
- ('author', admin.RelatedOnlyFieldListFilter),
- )
-
- Assuming ``author`` is a ``ForeignKey`` to a ``User`` model, this will
- limit the ``list_filter`` choices to the users who have written a book
- instead of listing all users.
-
- You can filter empty values using ``EmptyFieldListFilter``, which can
- filter on both empty strings and nulls, depending on what the field
- allows to store::
-
- class BookAdmin(admin.ModelAdmin):
- list_filter = (
- ('title', admin.EmptyFieldListFilter),
- )
-
- .. note::
-
- The ``FieldListFilter`` API is considered internal and might be
- changed.
-
- .. note::
-
- The :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
- field is not supported.
-
- List filter's typically appear only if the filter has more than one choice.
- A filter's ``has_output()`` method controls whether or not it appears.
-
- It is possible to specify a custom template for rendering a list filter::
-
- class FilterWithCustomTemplate(admin.SimpleListFilter):
- template = "custom_template.html"
+ list page of the admin.
- See the default template provided by Django (``admin/filter.html``) for
- a concrete example.
+ At it's simplest ``list_filter`` takes a list or tuple of field names to
+ activate filtering upon, but several more advanced options as available.
+ See :ref:`modeladmin-list-filters` for the details.
.. attribute:: ModelAdmin.list_max_show_all