page templates & views reordering

This commit is contained in:
bkfox 2020-09-22 00:51:00 +02:00
parent 5a17d034c4
commit ea17141321
13 changed files with 172 additions and 145 deletions

View File

@ -42,6 +42,7 @@ class SoundAdmin(admin.ModelAdmin):
'type', 'duration', 'is_public', 'is_good_quality', 'type', 'duration', 'is_public', 'is_good_quality',
'audio'] 'audio']
list_filter = ('type', 'is_good_quality', 'is_public') list_filter = ('type', 'is_good_quality', 'is_public')
list_editable = ['name', 'type', 'is_public']
search_fields = ['name', 'program__title'] search_fields = ['name', 'program__title']
fieldsets = [ fieldsets = [

View File

@ -218,25 +218,25 @@ class NavItem(models.Model):
page = models.ForeignKey(StaticPage, models.CASCADE, page = models.ForeignKey(StaticPage, models.CASCADE,
verbose_name=_('page'), blank=True, null=True, verbose_name=_('page'), blank=True, null=True,
limit_choices_to={'attach_to__isnull': True}) limit_choices_to={'attach_to__isnull': True})
#target_type = models.ForeignKey(
# ContentType, models.CASCADE, blank=True, null=True)
#target_id = models.PositiveSmallIntegerField(blank=True, null=True)
#target = GenericForeignKey('target_type', 'target_id')
class Meta: class Meta:
verbose_name = _('Menu item') verbose_name = _('Menu item')
verbose_name_plural = _('Menu items') verbose_name_plural = _('Menu items')
ordering = ('order', 'pk') ordering = ('order', 'pk')
def get_url(self):
return self.url if self.url else \
self.page.get_absolute_url() if self.page else None
def render(self, request, css_class='', active_class=''): def render(self, request, css_class='', active_class=''):
if active_class and request.path.startswith(self.url): url = self.get_url()
if active_class and request.path.startswith(url):
css_class += ' ' + active_class css_class += ' ' + active_class
if not self.url: if not url:
return self.text return self.text
elif not css_class: elif not css_class:
return format_html('<a href="{}">{}</a>', self.url, self.text) return format_html('<a href="{}">{}</a>', url, self.text)
else: else:
return format_html('<a href="{}" class="{}">{}</a>', self.url, return format_html('<a href="{}" class="{}">{}</a>', url,
css_class, self.text) css_class, self.text)

View File

@ -10,21 +10,6 @@ Usefull context:
- sidebar_object_list: item to display in sidebar - sidebar_object_list: item to display in sidebar
- sidebar_url_name: url name sidebar item complete list - sidebar_url_name: url name sidebar item complete list
- sidebar_url_parent: parent page for sidebar items complete list - sidebar_url_parent: parent page for sidebar items complete list
Blocks:
- assets
- head_title
- head_extra
- top_nav
- header:
- title
- subtitle
- header_meta
- main:
- filters
- cover
- sidebar:
- sidebar_title
{% endcomment %} {% endcomment %}
{% load static i18n thumbnail aircox %} {% load static i18n thumbnail aircox %}
@ -112,6 +97,7 @@ Blocks:
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{# TODO: change block name #}
{% if has_filters %} {% if has_filters %}
{% comment %}Translators: extra toolbar displayed on the top of page lists {% endcomment %} {% comment %}Translators: extra toolbar displayed on the top of page lists {% endcomment %}
<nav class="navbar toolbar" <nav class="navbar toolbar"

View File

@ -1,8 +1,5 @@
{% extends "aircox/base.html" %} {% extends "aircox/base.html" %}
{% comment %} {% comment %}Display detail of a BasePage{% endcomment %}
This template is only used in order to have correct page <title></title>,
otherwise use base.html
{% endcomment %}
{% block head_title %} {% block head_title %}
{% block title %}{{ page.title }}{% endblock %} {% block title %}{{ page.title }}{% endblock %}

View File

@ -0,0 +1,85 @@
{% extends "aircox/base.html" %}
{% comment %}Display a list of BasePages{% endcomment %}
{% load i18n aircox %}
{% block head_title %}
{% block title %}
{% if not page or not page.title %}
{% if not parent %}{{ view.model|verbose_name:True|title }}
{% else %}
{% with parent.title as title %}
{% with model|default:"Publications"|verbose_name:True|capfirst as model %}
{% comment %}Translators: title when pages are filtered for a specific parent page, e.g.: Articles of My Incredible Show{% endcomment %}
{% blocktrans %}{{ model }} of {{ title }}{% endblocktrans %}
{% endwith %}
{% endwith %}
{% endif %}
{% else %}{{ block.super }}
{% endif %}
{% endblock %}
&mdash;
{{ station.name }}
{% endblock %}
{% block main %}{{ block.super }}
<section role="list">
{% block pages_list %}
{% with has_headline=True %}
{% for object in object_list %}
{% block list_object %}
{% include object.item_template_name|default:item_template_name %}
{% endblock %}
{% empty %}
{% blocktrans %}There is nothing published here...{% endblocktrans %}
{% endfor %}
{% endwith %}
{% endblock %}
</section>
{% if is_paginated %}
<hr/>
{% update_query request.GET.copy page=None as GET %}
{% with GET.urlencode as GET %}
<nav class="pagination is-centered" role="pagination" aria-label="{% trans "pagination" %}">
{% block pagination %}
{% if page_obj.has_previous %}
<a href="?{{ GET }}&page={{ page_obj.previous_page_number }}" class="pagination-previous">
{% else %}
<a class="pagination-previous" disabled>
{% endif %}
{% comment %}Translators: Bottom of the list, "previous page"{% endcomment %}
{% trans "Previous" %}</a>
{% if page_obj.has_next %}
<a href="?{{ GET }}&page={{ page_obj.next_page_number }}" class="pagination-next">
{% else %}
<a class="pagination-next" disabled>
{% endif %}
{% comment %}Translators: Bottom of the list, "Nextpage"{% endcomment %}
{% trans "Next" %}</a>
<ul class="pagination-list">
{% for i in paginator.page_range %}
<li>
{% comment %}
<form action="?{{ GET }}">
{% for get in GET %}
<input type="hidden" name="{{ get.0 }}" value="{{ get.1 }}" />
{% endfor %}
<input type="number" name="page" value="{{ page_obj.number }}" />
</form>
{% endcomment %}
<a class="pagination-link {% if page_obj.number == i %}is-current{% endif %}"
href="?{{ GET }}&page={{ i }}">{{ i }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}
</nav>
{% endwith %}
{% endif %}
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "aircox/page.html" %} {% extends "aircox/page_list.html" %}
{% comment %}List of diffusions as a timetable{% endcomment %} {% comment %}List of diffusions as a timetable{% endcomment %}
{% load i18n aircox humanize %} {% load i18n aircox humanize %}
@ -20,7 +20,7 @@
{% endwith %} {% endwith %}
{% endblock %} {% endblock %}
{% block main %}{{ block.super }} {% block pages_list %}
{% with hide_schedule=True %} {% with hide_schedule=True %}
<section role="list"> <section role="list">
<div id="timetable-{{ date|date:"Y-m-d" }}"> <div id="timetable-{{ date|date:"Y-m-d" }}">
@ -41,11 +41,5 @@
</div> </div>
</section> </section>
{% endwith %} {% endwith %}
{% comment %}
<nav class="column menu is-one-third-desktop" role="menu">
</nav>
{% endcomment %}
{% endblock %} {% endblock %}

View File

@ -1,4 +1,5 @@
{% extends "aircox/page_list.html" %} {% extends "aircox/page_list.html" %}
{% comment %}Home page{% endcomment %}
{% load i18n %} {% load i18n %}
{% block head_title %}{{ station.name }}{% endblock %} {% block head_title %}{{ station.name }}{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "aircox/page.html" %} {% extends "aircox/page_list.html" %}
{% comment %}List of logs for a specific date{% endcomment %} {% comment %}List of logs for a specific date{% endcomment %}
{% load i18n humanize aircox %} {% load i18n humanize aircox %}
@ -21,7 +21,7 @@
{% endwith %} {% endwith %}
{% endblock %} {% endblock %}
{% block main %}{{ block.super }} {% block pages_list %}
<section> <section>
{# <h4 class="subtitle size-4">{{ date }}</h4> #} {# <h4 class="subtitle size-4">{{ date }}</h4> #}
{% include "aircox/widgets/log_list.html" %} {% include "aircox/widgets/log_list.html" %}

View File

@ -1,10 +1,9 @@
{% extends "aircox/page.html" %} {% extends "aircox/basepage.html" %}
{% load static i18n humanize honeypot %} {% load static i18n humanize honeypot %}
{% comment %} {% comment %}
Base template used to display a page Base template used to display a Page
Context: Context:
- title: title
- page: page - page: page
{% endcomment %} {% endcomment %}

View File

@ -1,22 +1,7 @@
{% extends "aircox/page.html" %} {% extends "aircox/basepage_list.html" %}
{% comment %}Display a list of pages{% endcomment %} {% comment %}Display a list of Pages{% endcomment %}
{% load i18n aircox %} {% load i18n aircox %}
{% block title %}
{% if not page or not page.title %}
{% if not parent %}{{ view.model|verbose_name:True|title }}
{% else %}
{% with parent.title as title %}
{% with model|default:"Publications"|verbose_name:True|capfirst as model %}
{% comment %}Translators: title when pages are filtered for a specific parent page, e.g.: Articles of My Incredible Show{% endcomment %}
{% blocktrans %}{{ model }} of {{ title }}{% endblocktrans %}
{% endwith %}
{% endwith %}
{% endif %}
{% else %}{{ block.super }}
{% endif %}
{% endblock %}
{% block filters %} {% block filters %}
{# FIXME #} {# FIXME #}
{% if filter_categories %} {% if filter_categories %}
@ -63,56 +48,3 @@
{% endblock %} {% endblock %}
{% block main %}{{ block.super }}
<section role="list">
{% block pages_list %}
{% with has_headline=True %}
{% for object in object_list %}
{% block list_object %}
{% include object.item_template_name|default:item_template_name %}
{% endblock %}
{% empty %}
{% blocktrans %}There is nothing published here...{% endblocktrans %}
{% endfor %}
{% endwith %}
{% endblock %}
</section>
{% if is_paginated %}
<hr/>
{% update_query request.GET.copy page=None as GET %}
{% with GET.urlencode as GET %}
<nav class="pagination is-centered" role="pagination" aria-label="{% trans "pagination" %}">
{% block pagination %}
{% if page_obj.has_previous %}
<a href="?{{ GET }}&page={{ page_obj.previous_page_number }}" class="pagination-previous">
{% else %}
<a class="pagination-previous" disabled>
{% endif %}
{% comment %}Translators: Bottom of the list, "previous page"{% endcomment %}
{% trans "Previous" %}</a>
{% if page_obj.has_next %}
<a href="?{{ GET }}&page={{ page_obj.next_page_number }}" class="pagination-next">
{% else %}
<a class="pagination-next" disabled>
{% endif %}
{% comment %}Translators: Bottom of the list, "Nextpage"{% endcomment %}
{% trans "Next" %}</a>
<ul class="pagination-list">
{% for i in paginator.page_range %}
<li>
<a class="pagination-link {% if page_obj.number == i %}is-current{% endif %}"
href="?{{ GET }}&page={{ i }}">{{ i }}</a>
</li>
{% endfor %}
</ul>
{% endblock %}
</nav>
{% endwith %}
{% endif %}
{% endblock %}

View File

@ -60,13 +60,13 @@ urls = [
path(_('publications/'), path(_('publications/'),
views.PageListView.as_view(model=models.Page), name='page-list'), views.PageListView.as_view(model=models.Page), name='page-list'),
path(_('pages/'), views.PageListView.as_view( path(_('pages/'), views.BasePageListView.as_view(
model=models.StaticPage, model=models.StaticPage,
queryset=models.StaticPage.objects.filter(attach_to__isnull=True), queryset=models.StaticPage.objects.filter(attach_to__isnull=True),
), ),
name='static-page-list' name='static-page-list'
), ),
path(_('pages/<slug:slug>/'), views.PageDetailView.as_view( path(_('pages/<slug:slug>/'), views.BasePageDetailView.as_view(
model=models.StaticPage, model=models.StaticPage,
queryset=models.StaticPage.objects.filter(attach_to__isnull=True), queryset=models.StaticPage.objects.filter(attach_to__isnull=True),
), ),

View File

@ -6,7 +6,7 @@ from .home import HomeView
from .article import ArticleDetailView, ArticleListView from .article import ArticleDetailView, ArticleListView
from .episode import EpisodeDetailView, EpisodeListView, DiffusionListView from .episode import EpisodeDetailView, EpisodeListView, DiffusionListView
from .log import LogListView, LogListAPIView from .log import LogListView, LogListAPIView
from .page import PageDetailView, PageListView from .page import BasePageListView, BasePageDetailView, PageListView, PageDetailView
from .program import ProgramDetailView, ProgramListView, \ from .program import ProgramDetailView, ProgramListView, \
ProgramPageDetailView, ProgramPageListView ProgramPageDetailView, ProgramPageListView

View File

@ -12,62 +12,47 @@ from .base import BaseView
from .mixins import AttachedToMixin, ParentMixin from .mixins import AttachedToMixin, ParentMixin
__all__ = ['PageDetailView', 'PageListView'] __all__ = ['BasePageListView', 'BasePageDetailView', 'PageDetailView', 'PageListView']
class PageListView(AttachedToMixin, ParentMixin, BaseView, ListView): class BasePageListView(AttachedToMixin, ParentMixin, BaseView, ListView):
template_name = 'aircox/page_list.html' """ Base view class for BasePage list. """
template_name = 'aircox/basepage_list.html'
item_template_name = 'aircox/widgets/page_item.html' item_template_name = 'aircox/widgets/page_item.html'
has_sidebar = True has_sidebar = True
has_filters = True
paginate_by = 20 paginate_by = 2
has_headline = True has_headline = True
categories = None
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
self.categories = set(self.request.GET.getlist('categories'))
return super().get(*args, **kwargs) return super().get(*args, **kwargs)
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset().select_subclasses().published() \ return super().get_queryset().select_subclasses().published() \
.select_related('cover', 'category') .select_related('cover')
# category can be filtered based on request.GET['categories']
# (by id)
if self.categories:
qs = qs.filter(category__slug__in=self.categories)
return qs.order_by('-pub_date')
def get_categories_queryset(self):
# TODO: use generic reverse field lookup
categories = self.model.objects.published() \
.filter(category__isnull=False) \
.values_list('category', flat=True)
return Category.objects.filter(id__in=categories)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs.setdefault('item_template_name', self.item_template_name) kwargs.setdefault('item_template_name', self.item_template_name)
kwargs.setdefault('filter_categories', self.get_categories_queryset())
kwargs.setdefault('categories', self.categories)
kwargs.setdefault('has_headline', self.has_headline) kwargs.setdefault('has_headline', self.has_headline)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class PageDetailView(BaseView, DetailView): class BasePageDetailView(BaseView, DetailView):
""" Base view class for pages. """ """ Base view class for BasePage. """
template_name = 'aircox/basepage_detail.html'
context_object_name = 'page' context_object_name = 'page'
has_filters = False has_filters = False
def get_queryset(self): def get_queryset(self):
return super().get_queryset().select_related('cover', 'category') return super().get_queryset().select_related('cover')
# This should not exists: it allows mapping not published pages # This should not exists: it allows mapping not published pages
# or it should be only used for trashed pages. # or it should be only used for trashed pages.
def not_published_redirect(self, page): def not_published_redirect(self, page):
""" """
When a page is not published, redirect to the returned url instead When a page is not published, redirect to the returned url instead of an
of an HTTP 404 code. """ HTTP 404 code.
"""
return None return None
def get_object(self): def get_object(self):
@ -85,6 +70,55 @@ class PageDetailView(BaseView, DetailView):
def get_page(self): def get_page(self):
return self.object return self.object
class PageListView(BasePageListView):
""" Page list view. """
template_name = None
has_filters = True
categories = None
def get(self, *args, **kwargs):
self.categories = set(self.request.GET.getlist('categories'))
return super().get(*args, **kwargs)
def get_template_names(self):
return super().get_template_names() + ['aircox/page_list.html']
def get_queryset(self):
qs = super().get_queryset().select_related('category') \
.order_by('-pub_date')
# category can be filtered based on request.GET['categories']
# (by id)
if self.categories:
qs = qs.filter(category__slug__in=self.categories)
return qs
def get_categories_queryset(self):
# TODO: use generic reverse field lookup
categories = self.model.objects.published() \
.filter(category__isnull=False) \
.values_list('category', flat=True)
return Category.objects.filter(id__in=categories)
def get_context_data(self, **kwargs):
kwargs.setdefault('filter_categories', self.get_categories_queryset())
kwargs.setdefault('categories', self.categories)
return super().get_context_data(**kwargs)
class PageDetailView(BaseView, DetailView):
""" Base view class for pages. """
template_name = None
context_object_name = 'page'
has_filters = False
def get_template_names(self):
return super().get_template_names() + ['aircox/page_detail.html']
def get_queryset(self):
return super().get_queryset().select_related('category')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
if self.object.allow_comments and not 'comment_form' in kwargs: if self.object.allow_comments and not 'comment_form' in kwargs:
kwargs['comment_form'] = CommentForm() kwargs['comment_form'] = CommentForm()
@ -109,5 +143,3 @@ class PageDetailView(BaseView, DetailView):
return self.get(request, *args, **kwargs) return self.get(request, *args, **kwargs)