from django.contrib.admin import filters from django.db import models from django.utils.http import urlencode from django.utils.translation import gettext_lazy as _ __all__ = ("DateFieldFilter", "DateTimeFieldFilter") class DateFieldFilter(filters.FieldListFilter): """Display date input.""" template = "admin/aircox/filters/date_filter.html" input_type = "date" def __init__(self, field, request, params, model, model_admin, field_path): self.field_generic = "%s__" % field_path self.date_params = { k: v for k, v in params.items() if k.startswith(self.field_generic) } exact_lookup = ( "date" if isinstance(field, models.DateTimeField) else "exact" ) # links as: (label, param, input_type|None, value) self.links = [ (_("Exact"), self.field_generic + exact_lookup, self.input_type), (_("Since"), self.field_generic + "gte", self.input_type), (_("Until"), self.field_generic + "lte", self.input_type), ] if field.null: self.links.insert( 0, (_("None"), self.field_generic + "isnull", None, "1") ) self.query_attrs = { k: v for k, v in request.GET.items() if k not in self.date_params } self.query_string = urlencode(self.query_attrs) super().__init__( field, request, params, model, model_admin, field_path ) def expected_parameters(self): return [link[1] for link in self.links] def choices(self, changelist): yield { "label": _("Any"), "type": None, "query_string": self.query_string, } for link in self.links: value = len(link) > 3 and link[3] or self.date_params.get(link[1]) yield { "label": link[0], "name": link[1], "value": value, "type": link[2], "query_attrs": self.query_attrs, "query_string": urlencode({link[1]: value}) + "&" + self.query_string if value else self.query_string, } class DateTimeFieldFilter(DateFieldFilter): """Display datetime input.""" input_type = "datetime-local" filters.FieldListFilter.register( lambda f: isinstance(f, models.DateField), DateFieldFilter, take_priority=True, ) filters.FieldListFilter.register( lambda f: isinstance(f, models.DateTimeField), DateTimeFieldFilter, take_priority=True, )