Queries ------- .. _override-operator: How do I override what operator is used for a query? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.query_operator_to_q_operator The member `query_operator_to_q_operator` for `Filter` is used to convert from e.g. `:` to `icontains`. You can specify another callable here: .. code-block:: python Table( auto__model=Track, columns__album__filter__query_operator_to_q_operator=lambda op: 'exact', ) The above will force the album name to always be looked up with case sensitive match even if the user types `album▼ Hide result
Toggle structure
Without the filter selected: .. raw:: html
► Show result
Toggle structure
How do I control the name used in the advanced query? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.query_name By default the names of filters are derived from the name you specify or from the model field name. For deeply nested names, double underscores are replaced with single underscores, and those names can become a bit unwieldy. You can then override this with `query_name`: .. code-block:: python track_table = Table( auto__model=Track, auto__include=['name', 'album', 'album__artist__name'], columns__album_artist_name__filter=dict( include=True, query_name='artist', ), ) .. raw:: html
▼ Hide result
Toggle structure
How do I filter on the thing itself? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.attr .. uses Filter. Filtering a table on the thing itself is sometimes useful, but can be a bit unintuitive: .. code-block:: python albums = Table( auto__model=Album, auto__include=['name', 'artist', 'year'], query__filters__album=Filter.choice_queryset( attr=None, choices=Album.objects.all(), value_to_q=lambda value_string_or_f, **_: Q(pk=value_string_or_f) if value_string_or_f else Q(), ), ) .. raw:: html
▼ Hide result
Toggle structure
How do I style the query container? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Query.attrs .. uses Query.tag .. uses Query.form_container The `Query` component renders a container element that wraps the filter form. You can configure its tag and attributes directly. The simple (GUI) form itself is wrapped in `form_container`, which you can configure the same way: .. code-block:: python albums = Table( auto__model=Album, auto__include=['name', 'artist', 'year'], columns__name__filter__include=True, query__attrs__style__border='2px solid red', ) .. raw:: html
▼ Hide result
Toggle structure
.. _query-filter-rows: How does a query filter the rows, and how do I post-process them? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Query.filter .. uses Query.filters .. uses Query.rows .. uses Query.model .. uses Query.postprocess A `Query` holds a set of `filters` and the `rows` (and `model`) it filters. When bound it builds a `Q` from the request, and its `filter` method applies that to the `rows`. Use `postprocess` to operate on the resulting rows afterwards. A `Query` is usually created for you by a `Table`, but you can declare and use one on its own: .. code-block:: python class AlbumQuery(Query): name = Filter() year = Filter.integer() query = AlbumQuery(rows=Album.objects.all()) .. raw:: html
▼ Hide result
Toggle structure
.. _query-auto-config: How do I choose which filters are generated from a model? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses QueryAutoConfig.model .. uses QueryAutoConfig.exclude .. uses QueryAutoConfig.default_included .. uses QueryAutoConfig.rows Like tables and forms, a `Query` can introspect a model. Pass `auto__model` (or `auto__rows`) and pick the filters with `auto__include`/`auto__exclude`, or flip the default with `auto__default_included`: .. code-block:: python query = Query( auto__model=Album, auto__exclude=['year'], ) .. raw:: html
▼ Hide result
Toggle structure
.. _filter-gui-field: How do I configure a filter's GUI field? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.field .. uses Filter.choices .. uses Filter.search_fields Each filter has a GUI form field, configured through the filter's `field` namespace. For choice filters `choices` is the list of options, and `search_fields` controls which model fields the autocomplete of a `choice_queryset` filter searches: .. code-block:: python albums = Table( auto__model=Album, columns__year__filter=dict( include=True, field__include=True, ), columns__artist__filter=dict( include=True, search_fields=['name'], ), ) .. raw:: html
▼ Hide result
Toggle structure
.. _filter-matching: How do I customize how a single filter matches? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.query_operator_for_field .. uses Filter.unary .. uses Filter.parse .. uses Filter.is_valid_filter .. uses Filter.pk_lookup_to_q .. uses Filter.model .. uses Filter.model_field .. uses Filter.model_field_name Lower-level hooks change how an individual filter behaves: - `query_operator_for_field` is the operator used for the simple (GUI) form, e.g. `=` for exact-ish matching or `:` for "contains". - `parse` parses the user's input string into a value. - `unary` marks a filter as usable without a value in the advanced query language. - `is_valid_filter` decides whether a filter is allowed to be part of a query at all. - `pk_lookup_to_q` controls how a lookup by primary key is turned into a `Q`. Filters generated from a model also carry `model`, `model_field` and `model_field_name` (the same introspection you get on columns and fields), so a custom hook can read the Django field's metadata when it needs to. .. code-block:: python albums = Table( auto__model=Album, columns__name__filter=dict( include=True, query_operator_for_field=':', ), ) .. raw:: html
▼ Hide result
Toggle structure
.. _advanced-query: How do I customize the advanced query language area? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Query.advanced A `Query` with filters offers an "advanced" free-text query language alongside the GUI form, with a link to toggle between them. Configure that toggle (and the advanced area) through the `advanced` namespace: .. code-block:: python albums = Table( auto__model=Album, columns__name__filter__include=True, query__advanced__toggle__attrs__class__advanced_toggle=True, ) .. raw:: html
▼ Hide result
Toggle structure
.. _filter-multi-select: How do I let a filter match several values at once? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. uses Filter.related .. uses Filter.multi_choice_queryset A filter on a foreign key (the `related` shortcut, which is what you get by default for an `album` or `artist` column) normally lets the user pick a single value in the GUI. Pass `multi_select=True` to turn it into a multi-select where the chosen values are OR:ed together: .. code-block:: python tracks = Table( auto__model=Track, auto__include=['name', 'album'], columns__album__filter__include=True, columns__album__filter__multi_select=True, ) .. raw:: html
▼ Hide result
Toggle structure
Selecting two albums now produces a query like ``album__pk=1 OR album__pk=2`` instead of forcing the user to choose just one.