Multiple Filter-By¶
Example Overview¶
This example filters options against multiple form fields at once by passing a list of tuples to filter_by, narrowing the available articles to those matching both the selected Magazine AND the selected Status. Each condition is combined with AND logic and skipped when its field is empty, making this the pattern to use for multi-dimensional filtering such as articles by publication and status or products by category and availability.
Key Code Segments¶
Forms¶
This example uses the new list format for filter_by to specify multiple filter conditions:
Form Definition
from django import forms
from django_tomselect.app_settings import TomSelectConfig, PluginDropdownHeader, PluginClearButton, PluginRemoveButton
from django_tomselect.forms import TomSelectModelChoiceField, TomSelectModelMultipleChoiceField, TomSelectChoiceField
class MultipleFilterByForm(forms.Form):
"""Demonstrates filter_by with multiple field-based filters."""
magazine = TomSelectModelChoiceField(
config=TomSelectConfig(
url="autocomplete-magazine",
value_field="id",
label_field="name",
placeholder="Select a magazine...",
plugin_clear_button=PluginClearButton(title="Clear magazine"),
),
required=False,
)
status = TomSelectChoiceField(
config=TomSelectConfig(
url="autocomplete-article-status",
value_field="value",
label_field="label",
placeholder="Select a status...",
plugin_clear_button=PluginClearButton(title="Clear status"),
),
required=False,
)
# Articles filtered by BOTH magazine AND status
articles = TomSelectModelMultipleChoiceField(
config=TomSelectConfig(
url="autocomplete-article",
value_field="id",
label_field="title",
# Multiple field filters - filter by magazine AND status
filter_by=[
("magazine", "magazine_id"), # Filter by selected magazine
("status", "status"), # AND by selected status
],
placeholder="Select articles (filtered by magazine and status)...",
plugin_dropdown_header=PluginDropdownHeader(
title="Articles",
extra_columns={
"status": "Status",
"magazine_name": "Magazine",
},
),
plugin_clear_button=PluginClearButton(title="Clear articles"),
plugin_remove_button=PluginRemoveButton(),
),
required=False,
)
Explanation:
The
filter_byparameter accepts a list of 2-tuples:[("form_field", "lookup_field"), ...]Each tuple specifies: the form field name to get the value from, and the model field to filter by
All conditions are combined with AND logic
If a form field has no value, that filter condition is skipped
How It Works¶
When both Magazine and Status are selected:
The JavaScript reads values from both form fields
The autocomplete URL includes multiple
fparameters:?q=search&f='magazine__magazine_id=5'&f='status__status=published'
The server applies both filters with AND logic
Only articles matching BOTH conditions are returned
Templates¶
Template Code
{% extends 'example/base_with_bootstrap5.html' %}
{% block content %}
<div class="card">
<div class="card-header">
<h2>Multiple Filter By Demo</h2>
</div>
<div class="card-body">
<p>Select a magazine AND/OR a status to filter the available articles.</p>
<form method="post">
{% csrf_token %}
<div class="mb-3">
<label for="{{ form.magazine.id_for_label }}" class="form-label">Magazine</label>
{{ form.magazine }}
</div>
<div class="mb-3">
<label for="{{ form.status.id_for_label }}" class="form-label">Status</label>
{{ form.status }}
</div>
<div class="mb-3">
<label for="{{ form.articles.id_for_label }}" class="form-label">Articles</label>
{{ form.articles }}
<div class="form-text">Articles are filtered by both magazine AND status above.</div>
</div>
</form>
</div>
</div>
{% endblock %}
This template snippet is abridged. The live template also defines a
{% block extra_header %}containing{{ form.media }}and a<style>block; without{{ form.media }}the widgets render unstyled.
Implementation Notes¶
Key Features:
Combines multiple
filter_byconditions with AND logicEach filter is optional - if not selected, that condition is ignored
Fully backwards compatible with the single-tuple format
Comparison with Single Filter:
Single Filter
Multiple Filters
filter_by=('field', 'lookup')filter_by=[('field1', 'lookup1'), ('field2', 'lookup2')]One condition
Multiple AND conditions
Form field value only
Form field values only
See the Constant Filter-By example for filtering with constant values.