ListView
The Fastview generic ListView
adds support for admin-style filtering, searching and
ordering, with a default template similar to the Django admin changelist. These can all
be changed and customised as necessary.
Templates
The ListView
follows Fastview’s standard template lookup rules
annotated objects
filters
search_fields
page_range
label_orders
Display fields
The fields
attribute can take a list of model attribute names:
class BlogList(ListView):
fields = ["name", "is_published"]
These are converted into display objects; to customise how a field is shown, or to add a
custom field which isn’t a model attribute, you can create your own DisplayValue
class and pass that in as an object in the list. See Display objects for full details.
Filters
The ListView
supports filters = [...]
attribute. This can be a list of model
field names or Filter
instances.
Fastview has 3 built-in filters:
Filter
: a choice-based filter. Choices can either be specified on the constructor, on a subclass, or collected from the model field the filter is acting on. Subclasses can also define their ownget_choices()
method to override the default behaviour.DateHierarchyFilter
: lists active years for the DateField or DateTimeField, and then when a year is selected, filters by that year and lists active months to drill down to.BooleanFilter
: Yes/No filter for a BooleanField
If you specify the name of the field in the filters
list, the most appropriate
filter will be chosen for you.
Custom filter on a field
It can be useful to filter a field by options other than its values.
For example, to allow you to filter an empty CharField
:
from fastview import ListView
from fastview.views.filters import Filter
class EmptyFilter(Filter):
choices = (
('empty': 'Empty'),
('set': 'Set'),
)
def process(self, qs):
if self.value == 'empty':
return qs.filter(**{self.field_name: ''})
elif self.value == 'set':
return qs.exclude(**{self.field_name: ''})
return qs
class Entries(ListView):
model = Entry
filters = ['publish_date', 'is_published', EmptyFilter('title')]
Custom filter on a method
It can also be useful to filter on values returned from model methods, such as the
was_published_recently
field in the tutorial. Because it’s a
method not a field, it can’t be used to filter a queryset directly, but we can write a
custom filter to do it instead:
import datetime
from fastview.views.filters import BooleanFilter
class RecentlyPublishedFilter(BooleanFilter):
def process(self, qs):
if self.boolean is None:
return qs
now = timezone.now()
date_range = {
"pub_date__gte": now - datetime.timedelta(days=30),
"pub_date__lte": now,
}
if self.boolean is True:
return qs.filter(**date_range)
return qs.exclude(**date_range)
class PollViewGroup(ModelViewGroup):
# ...
index_view = {
# ...
"filters": ["pub_date", RecentlyPublishedFilter(param="recent")],
}
There are few things going on here:
Our filter subclasses
fastview.views.filters.BooleanFilter
, as that’s going to be the closest built-in filter to what we need - it lets the user pick yes or no.We override the
process
method to filter the queryset.self.value
is going to beTrue
orFalse
, orNone
if neither is selected.We then instantiate our filter class with
param="recent"
, which tells Fastview the key to use in the URL querystring, eg/polls/?recent=1
will make the filter valueTrue
.The instantiated filter class can then be put in the
filters
array in the order you want the filters to be shown.
API reference
- class fastview.views.generic.ListView(**kwargs)
Bases:
fastview.views.mixins.DisplayFieldMixin
,fastview.views.mixins.ModelFastViewMixin
,django.views.generic.list.ListView
A permission-aware ListView with support for ViewGroups
- action: Optional[str] = 'list'
Name of action for the ViewGroup
- action_label: Optional[str] = 'List'
Label for this action
- context_annotated_name = 'annotated_object_list'
Context variable name for the annotated object list.
- default_template_name: str = 'fastview/list.html'
The default template name
- fields: Optional[List[Union[str, DisplayValue]]] = [<fastview.views.display.ObjectValue object>]
Example:
fields = [ 'field_name', # MyModel.field_name 'get_value', # MyModel.get_value() CustomValue(), # :class:`fastview.views.display.DisplayValue` subclass
Defaults to show the string value of the model instance
- filters: Optional[List[Union[str, BaseFilter]]] = None
List of available filters to apply to the list table.
The values can be
filter classes
or string values which correspond to model field names.Example:
filters = [ 'field_name', # MyModel.field_name CustomFilter(...), # :class:`fastview.views.filters.Filter` subclass
- get_context_data(**kwargs)
The template context has additional variables available:
annotated_object_list: List of (object, Can, fields) tuples filters: List of filters, bound to any query arguments page_range: Paginator page range (Django 3.2+) label_orders: List of (label, current_order, param_value) tuples for links in the table header
- get_filters() Dict[str, fastview.views.filters.BaseFilter]
Build filter list by looking up field strings and converting to Filter instances
Convert self.filters from:
['field_name', Filter('param', ...)]
to:
{ 'field_name': Filter('field_name', ...), 'param': Filter('param', ...), }
- get_ordering()
Build queryset ordering rule from the CSV list of DisplayValue slugs in
request.GET[PARAM_ORDER]
- get_queryset() django.db.models.query.QuerySet
Apply filters, search terms, ordering and limits to the queryset
- object_annotator_factory(object_list)
Generate an annotated object list without holding everything in memory
- Returns
A generator factory to annotate an object list.
In other words:
This takes a list of objects
It returns a clean generator function to iterate over those objects
It is not called until it reaches the template
It will be called each time it is referenced in the template, creating a clean generator, allowing the list to be iterated over more than once in the same template.
The generator yields
AnnotatedObject
objects for rendering
- request_ordering: Optional[Dict[str, str]] = None
Ordering params found in the request when getting the queryset
- row_permission = None
Permission
check to display individual rows.
- search_fields: Optional[List[str]] = None
List of fields to search
- title: str = '{verbose_name_plural}'
The page title, passed to template context for use in page title and headers. See
get_title()
for more details