from django.db import models from django.contrib.admin import filters from django.utils.translation import gettext_lazy as _ from django.utils.http import urlencode __all__ = ('DateFieldFilter', 'DateTimeField') 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)} # links as: (label, param, input_type|None, value) self.links = [(_('Exact'), self.field_generic + 'exact', 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)