From 36f5ee8b4437f6293d07ff8da10bbffaa138cf4c Mon Sep 17 00:00:00 2001 From: bkfox Date: Thu, 5 May 2022 12:53:30 +0200 Subject: [PATCH 1/3] add filters --- aircox/admin/filters.py | 32 +++++++++++++++++++ aircox/admin/page.py | 5 +-- aircox/models/page.py | 12 +++++-- .../admin/aircox/filters/date_filter.html | 20 ++++++++++++ .../admin/aircox/filters/datetime_filter.html | 7 ++++ .../admin/aircox/filters/filter.html | 4 +++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 aircox/admin/filters.py create mode 100644 aircox/templates/admin/aircox/filters/date_filter.html create mode 100644 aircox/templates/admin/aircox/filters/datetime_filter.html create mode 100644 aircox/templates/admin/aircox/filters/filter.html diff --git a/aircox/admin/filters.py b/aircox/admin/filters.py new file mode 100644 index 0000000..fa0bc12 --- /dev/null +++ b/aircox/admin/filters.py @@ -0,0 +1,32 @@ +from django.contrib.admin import filters +from django.utils.translation import gettext_lazy as _ + + +__all__ = ('DateFieldFilter',) + + +class DateFieldFilter(filters.FieldListFilter): + 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)} + + self.links = ((_('Exact'), self.field_generic + 'exact'), + (_('Since'), self.field_generic + 'gte'), + (_('Until'), self.field_generic + 'lte')) + 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): + for link in self.links: + yield {'label': link[0], + 'name': link[1], + 'value': self.date_params.get(link[1]), + 'type': self.input_type,} + + diff --git a/aircox/admin/page.py b/aircox/admin/page.py index ffbd444..9b666cd 100644 --- a/aircox/admin/page.py +++ b/aircox/admin/page.py @@ -8,9 +8,10 @@ from django.utils.translation import gettext_lazy as _ from adminsortable2.admin import SortableInlineAdminMixin from ..models import Category, Comment, NavItem, Page, StaticPage +from .filters import DateFieldFilter -__all__ = ['CategoryAdmin', 'PageAdmin', 'NavItemInline'] +__all__ = ('CategoryAdmin', 'PageAdmin', 'NavItemInline') @admin.register(Category) @@ -82,7 +83,7 @@ class PageAdmin(BasePageAdmin): list_display = BasePageAdmin.list_display + ('category',) list_editable = BasePageAdmin.list_editable + ('category',) - list_filter = BasePageAdmin.list_editable + ('category',) + list_filter = BasePageAdmin.list_filter + ('category', ('pub_date', DateFieldFilter)) search_fields = ('category__title',) fieldsets = deepcopy(BasePageAdmin.fieldsets) diff --git a/aircox/models/page.py b/aircox/models/page.py index b1c5123..8939508 100644 --- a/aircox/models/page.py +++ b/aircox/models/page.py @@ -38,7 +38,7 @@ class Category(models.Model): return self.title -class PageQuerySet(InheritanceQuerySet): +class BasePageQuerySet(InheritanceQuerySet): def draft(self): return self.filter(status=Page.STATUS_DRAFT) @@ -86,7 +86,7 @@ class BasePage(models.Model): _('content'), blank=True, null=True, ) - objects = PageQuerySet.as_manager() + objects = BasePageQuerySet.as_manager() detail_url_name = None item_template_name = 'aircox/widgets/page_item.html' @@ -149,6 +149,12 @@ class BasePage(models.Model): return cls(**cls.get_init_kwargs_from(page, **kwargs)) +class PageQuerySet(BasePageQuerySet): + def published(self): + return self.filter(status=Page.STATUS_PUBLISHED, + pub_date__lte=tz.now()) + + class Page(BasePage): """ Base Page model used for articles and other dated content. """ category = models.ForeignKey( @@ -163,6 +169,8 @@ class Page(BasePage): _('allow comments'), default=True, ) + objects = PageQuerySet.as_manager() + class Meta: verbose_name = _('Publication') verbose_name_plural = _('Publications') diff --git a/aircox/templates/admin/aircox/filters/date_filter.html b/aircox/templates/admin/aircox/filters/date_filter.html new file mode 100644 index 0000000..edea836 --- /dev/null +++ b/aircox/templates/admin/aircox/filters/date_filter.html @@ -0,0 +1,20 @@ +{% extends "./filter.html" %} +{% load static %} +{% block content %} +{% with choices|first as choice %} +
+ +
+ +
+
+{% endwith %} +{% endblock %} diff --git a/aircox/templates/admin/aircox/filters/datetime_filter.html b/aircox/templates/admin/aircox/filters/datetime_filter.html new file mode 100644 index 0000000..c96db85 --- /dev/null +++ b/aircox/templates/admin/aircox/filters/datetime_filter.html @@ -0,0 +1,7 @@ +{% extends "admin/aircox/filter.html" %} +{% block content %} +{% with choices|first as choice %} + +{% endwith %} +{% endblock %} + diff --git a/aircox/templates/admin/aircox/filters/filter.html b/aircox/templates/admin/aircox/filters/filter.html new file mode 100644 index 0000000..a630813 --- /dev/null +++ b/aircox/templates/admin/aircox/filters/filter.html @@ -0,0 +1,4 @@ +{% load i18n %} +

{% blocktranslate with filter_title=title %} By {{ filter_title }} {% endblocktranslate %}

+{% block content %}{% endblock %} + -- 2.30.2 From e44b77d0b3f495bcb7878fe1e0be34402dd441ed Mon Sep 17 00:00:00 2001 From: bkfox Date: Thu, 5 May 2022 14:45:23 +0200 Subject: [PATCH 2/3] admin filter for date and datetime using --- aircox/admin/__init__.py | 1 + aircox/admin/filters.py | 16 ++++++++++-- aircox/admin/page.py | 3 +-- aircox/models/page.py | 3 ++- .../admin/aircox/filters/date_filter.html | 26 +++++++++---------- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/aircox/admin/__init__.py b/aircox/admin/__init__.py index ce5dc4a..5fe7001 100644 --- a/aircox/admin/__init__.py +++ b/aircox/admin/__init__.py @@ -1,3 +1,4 @@ +from . import filters from .article import ArticleAdmin from .episode import DiffusionAdmin, EpisodeAdmin from .log import LogAdmin diff --git a/aircox/admin/filters.py b/aircox/admin/filters.py index fa0bc12..129d777 100644 --- a/aircox/admin/filters.py +++ b/aircox/admin/filters.py @@ -1,11 +1,13 @@ +from django.db import models from django.contrib.admin import filters from django.utils.translation import gettext_lazy as _ -__all__ = ('DateFieldFilter',) +__all__ = ('DateFieldFilter', 'DateTimeField') class DateFieldFilter(filters.FieldListFilter): + """ Display date input """ template = 'admin/aircox/filters/date_filter.html' input_type = 'date' @@ -13,7 +15,6 @@ class DateFieldFilter(filters.FieldListFilter): self.field_generic = '%s__' % field_path self.date_params = {k: v for k, v in params.items() if k.startswith(self.field_generic)} - self.links = ((_('Exact'), self.field_generic + 'exact'), (_('Since'), self.field_generic + 'gte'), (_('Until'), self.field_generic + 'lte')) @@ -30,3 +31,14 @@ class DateFieldFilter(filters.FieldListFilter): 'type': self.input_type,} +class DateTimeFieldFilter(DateFieldFilter): + """ Display datetime input """ + input_type = 'datetime' + + +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) + diff --git a/aircox/admin/page.py b/aircox/admin/page.py index 9b666cd..24a7bb8 100644 --- a/aircox/admin/page.py +++ b/aircox/admin/page.py @@ -8,7 +8,6 @@ from django.utils.translation import gettext_lazy as _ from adminsortable2.admin import SortableInlineAdminMixin from ..models import Category, Comment, NavItem, Page, StaticPage -from .filters import DateFieldFilter __all__ = ('CategoryAdmin', 'PageAdmin', 'NavItemInline') @@ -83,7 +82,7 @@ class PageAdmin(BasePageAdmin): list_display = BasePageAdmin.list_display + ('category',) list_editable = BasePageAdmin.list_editable + ('category',) - list_filter = BasePageAdmin.list_filter + ('category', ('pub_date', DateFieldFilter)) + list_filter = BasePageAdmin.list_filter + ('category', 'pub_date') search_fields = ('category__title',) fieldsets = deepcopy(BasePageAdmin.fieldsets) diff --git a/aircox/models/page.py b/aircox/models/page.py index 8939508..cfaf2d2 100644 --- a/aircox/models/page.py +++ b/aircox/models/page.py @@ -161,7 +161,8 @@ class Page(BasePage): Category, models.SET_NULL, verbose_name=_('category'), blank=True, null=True, db_index=True ) - pub_date = models.DateTimeField(blank=True, null=True) + pub_date = models.DateTimeField( + _('publication date'), blank=True, null=True, db_index=True) featured = models.BooleanField( _('featured'), default=False, ) diff --git a/aircox/templates/admin/aircox/filters/date_filter.html b/aircox/templates/admin/aircox/filters/date_filter.html index edea836..e600c4b 100644 --- a/aircox/templates/admin/aircox/filters/date_filter.html +++ b/aircox/templates/admin/aircox/filters/date_filter.html @@ -1,20 +1,18 @@ {% extends "./filter.html" %} {% load static %} + + {% block content %} -{% with choices|first as choice %} -
-
    - {% for choice in choices %} -
  • - - + {% for choice in choices %} +
    + + + -
  • - {% endfor %} -
-
- + +
- -{% endwith %} + {% endfor %} + {% endblock %} -- 2.30.2 From ff398d8e7f0567c32678c9cf1badfc03c068b73a Mon Sep 17 00:00:00 2001 From: bkfox Date: Thu, 5 May 2022 17:15:06 +0200 Subject: [PATCH 3/3] add url & make it work --- aircox/admin/filters.py | 33 ++++++++++++++----- .../admin/aircox/filters/date_filter.html | 14 ++++++-- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/aircox/admin/filters.py b/aircox/admin/filters.py index 129d777..ff70203 100644 --- a/aircox/admin/filters.py +++ b/aircox/admin/filters.py @@ -1,6 +1,7 @@ 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') @@ -15,25 +16,41 @@ class DateFieldFilter(filters.FieldListFilter): self.field_generic = '%s__' % field_path self.date_params = {k: v for k, v in params.items() if k.startswith(self.field_generic)} - self.links = ((_('Exact'), self.field_generic + 'exact'), - (_('Since'), self.field_generic + 'gte'), - (_('Until'), self.field_generic + 'lte')) + + # 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: - yield {'label': link[0], - 'name': link[1], - 'value': self.date_params.get(link[1]), - 'type': self.input_type,} + 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' + input_type = 'datetime-local' filters.FieldListFilter.register( diff --git a/aircox/templates/admin/aircox/filters/date_filter.html b/aircox/templates/admin/aircox/filters/date_filter.html index e600c4b..a176b95 100644 --- a/aircox/templates/admin/aircox/filters/date_filter.html +++ b/aircox/templates/admin/aircox/filters/date_filter.html @@ -5,14 +5,22 @@ {% block content %}
    {% for choice in choices %} -
    -
    +
  • + {% if choice.type %} + + {% for k, v in choice.query_attrs.items %} + + {% endfor %}
  • -
    + {% else %} + {{ choice.label }} + {% endif %} + {% endfor %}
{% endblock %} -- 2.30.2