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 new file mode 100644 index 0000000..ff70203 --- /dev/null +++ b/aircox/admin/filters.py @@ -0,0 +1,61 @@ +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) + diff --git a/aircox/admin/page.py b/aircox/admin/page.py index ffbd444..24a7bb8 100644 --- a/aircox/admin/page.py +++ b/aircox/admin/page.py @@ -10,7 +10,7 @@ from adminsortable2.admin import SortableInlineAdminMixin from ..models import Category, Comment, NavItem, Page, StaticPage -__all__ = ['CategoryAdmin', 'PageAdmin', 'NavItemInline'] +__all__ = ('CategoryAdmin', 'PageAdmin', 'NavItemInline') @admin.register(Category) @@ -82,7 +82,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') search_fields = ('category__title',) fieldsets = deepcopy(BasePageAdmin.fieldsets) diff --git a/aircox/models/page.py b/aircox/models/page.py index b1c5123..cfaf2d2 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,13 +149,20 @@ 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( 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, ) @@ -163,6 +170,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..a176b95 --- /dev/null +++ b/aircox/templates/admin/aircox/filters/date_filter.html @@ -0,0 +1,26 @@ +{% extends "./filter.html" %} +{% load static %} + + +{% block content %} +