diff --git a/website/models.py b/website/models.py
index 959ed89..48142c9 100644
--- a/website/models.py
+++ b/website/models.py
@@ -137,11 +137,12 @@ class Article (BasePost):
verbose_name_plural = _('Articles')
-
ProgramPost = Post.create_related_post(programs.Program, {
'title': 'name',
'content': 'description',
})
+
+
EpisodePost = Post.create_related_post(programs.Episode, {
'title': 'name',
'content': 'description',
diff --git a/website/routes.py b/website/routes.py
index 3602d52..57f72a4 100644
--- a/website/routes.py
+++ b/website/routes.py
@@ -2,22 +2,24 @@ from django.conf.urls import url
from django.utils import timezone
from website.models import *
+from website.views import *
-class Routes:
+class Router:
registry = []
def register (self, route):
if not route in self.registry:
self.registry.append(route)
+ def register_set (self, view_set):
+ for route in view_set.routes:
+ self.register(route)
+
def unregister (self, route):
self.registry.remove(route)
def get_urlpatterns (self):
- patterns = []
- for route in self.registry:
- patterns += route.get_urlpatterns() or []
- return patterns
+ return [ route.get_url() for route in self.registry ]
class Route:
@@ -62,12 +64,16 @@ class Route:
"""
Called by the view to get the queryset when it is needed
"""
+ pass
- def get_urlpatterns (self):
- view_kwargs = self.view_kwargs or {}
+ def get (self, request, **kwargs):
+ """
+ Called by the view to get the object when it is needed
+ """
+ pass
+ def get_url (self):
pattern = '^{}/{}'.format(self.base_name, self.Meta.name)
-
if self._meta['url_args']:
url_args = '/'.join([ '(?P<{}>{})'.format(arg, expr) \
for arg, expr in self._meta['url_args']
@@ -75,32 +81,26 @@ class Route:
pattern += '/' + url_args
pattern += '/?$'
- return [ url(
- pattern,
- self.view and self.view.as_view(
- route = self,
- model = self.model,
- **view_kwargs
- ),
- name = '{}'
- ) ]
+ kwargs = {
+ 'route': self,
+ }
+ if self.view_kwargs:
+ kwargs.update(self.view_kwargs)
+
+ return url(pattern, self.view, kwargs = kwargs, name = '{}')
-class SearchRoute (Route):
+class DetailRoute (Route):
class Meta:
- name = 'search'
- is_list = True
+ name = 'detail'
+ is_list = False
+ url_args = [
+ ('pk', '[0-9]+'),
+ ('slug', '(\w|-|_)*'),
+ ]
- def get_queryset (self, request, **kwargs):
- q = request.GET.get('q') or ''
- qs = self.model.objects
- for search_field in model.search_fields or []:
- r = self.model.objects.filter(**{ search_field + '__icontains': q })
- if qs: qs = qs | r
- else: qs = r
-
- qs.distinct()
- return qs
+ def get (self, request, **kwargs):
+ return self.model.objects.get(pk = int(kwargs['pk']))
class ThreadRoute (Route):
@@ -112,7 +112,7 @@ class ThreadRoute (Route):
]
def get_queryset (self, request, **kwargs):
- return self.model.objects.filter(thread__id = int(kwargs['pk']))
+ return self.model.objects.filter(thread__pk = int(kwargs['pk']))
class DateRoute (Route):
@@ -133,4 +133,21 @@ class DateRoute (Route):
)
+class SearchRoute (Route):
+ class Meta:
+ name = 'search'
+ is_list = True
+
+ def get_queryset (self, request, **kwargs):
+ q = request.GET.get('q') or ''
+ qs = self.model.objects
+ for search_field in model.search_fields or []:
+ r = self.model.objects.filter(**{ search_field + '__icontains': q })
+ if qs: qs = qs | r
+ else: qs = r
+
+ qs.distinct()
+ return qs
+
+
diff --git a/website/templates/website/list.html b/website/templates/website/list.html
index d75b077..d5293c3 100644
--- a/website/templates/website/list.html
+++ b/website/templates/website/list.html
@@ -1,9 +1,3 @@
-{# Parameters are: #}
-{# * pub: publication itself; pub.meta must have been eval() #}
-{# * threads: list of parent, from top to bottom, including itself #}
-{# #}
-{# * views: a view object used to know which view to use for links #}
-{# #}
{# {% extends embed|yesno:"website/single.html,website/base.html" %} #}
{% load i18n %}
@@ -11,6 +5,7 @@
{# {% load website_views %} #}
+{% block content %}
{% for post in object_list %}
{% endfor %}
+{% endblock %}
diff --git a/website/urls.py b/website/urls.py
index 7346238..70c944a 100644
--- a/website/urls.py
+++ b/website/urls.py
@@ -5,20 +5,42 @@ from website.views import *
from website.routes import *
-routes = Routes()
+class ProgramSet (ViewSet):
+ model = ProgramPost
+ name = 'programs'
-routes.register( SearchRoute(Article, PostListView) )
-routes.register( SearchRoute(ProgramPost, PostListView, base_name = 'programs') )
-#routes.register( SearchRoute(EpisodePost, PostListView, base_name = 'episodes') )
-
-routes.register( ThreadRoute(Article, PostListView) )
-routes.register( ThreadRoute(ProgramPost, PostListView, base_name = 'programs') )
-#routes.register( ThreadRoute(EpisodePost, PostListView, base_name = 'episodes') )
-
-routes.register( DateRoute(Article, PostListView) )
-routes.register( DateRoute(ProgramPost, PostListView, base_name = 'programs') )
-#routes.register( DateRoute(EpisodePost, PostListView, base_name = 'episodes') )
-
-urlpatterns = routes.get_urlpatterns()
+ list_routes = [
+ ThreadRoute,
+ SearchRoute,
+ DateRoute,
+ ]
+
+
+class EpisodeSet (ViewSet):
+ model = EpisodePost
+ name = 'episodes'
+
+ list_routes = [
+ ThreadRoute,
+ SearchRoute,
+ DateRoute,
+ ]
+
+
+class ArticleSet (ViewSet):
+ model = Article
+ list_routes = [
+ ThreadRoute,
+ SearchRoute,
+ DateRoute,
+ ]
+
+
+router = Router()
+router.register_set(ProgramSet())
+router.register_set(EpisodeSet())
+router.register_set(ArticleSet())
+
+urlpatterns = router.get_urlpatterns()
diff --git a/website/utils.py b/website/utils.py
deleted file mode 100644
index a31590c..0000000
--- a/website/utils.py
+++ /dev/null
@@ -1,83 +0,0 @@
-from django.db import models
-from django.utils import timezone, dateformat
-from programs.models import *
-
-
-class ListQueries:
- @staticmethod
- def search (qs, q):
- qs = qs.filter(tags__slug__in = re.compile(r'(\s|\+)+').split(q)) | \
- qs.filter(title__icontains = q) | \
- qs.filter(subtitle__icontains = q) | \
- qs.filter(content__icontains = q)
- qs.distinct()
- return qs
-
- @staticmethod
- def thread (qs, q):
- return qs.filter(parent = q)
-
- @staticmethod
- def next (qs, q):
- qs = qs.filter(date__gte = timezone.now())
- if q:
- qs = qs.filter(parent = q)
- return qs
-
- @staticmethod
- def prev (qs, q):
- qs = qs.filter(date__lte = timezone.now())
- if q:
- qs = qs.filter(parent = q)
- return qs
-
- @staticmethod
- def date (qs, q):
- if not q:
- q = timezone.datetime.today()
- if type(q) is str:
- q = timezone.datetime.strptime(q, '%Y%m%d').date()
-
- return qs.filter(date__startswith = q)
-
- class Diffusion:
- @staticmethod
- def episode (qs, q):
- return qs.filter(episode = q)
-
- @staticmethod
- def program (qs, q):
- return qs.filter(program = q)
-
-class ListQuery:
- model = None
- qs = None
-
- def __init__ (self, model, *kwargs):
- self.model = model
- self.__dict__.update(kwargs)
-
- def get_queryset (self, by, q):
- qs = model.objects.all()
- if model._meta.get_field_by_name('public'):
- qs = qs.filter(public = True)
-
- # run query set
- queries = Queries.__dict__.get(self.model) or Queries
- filter = queries.__dict__.get(by)
- if filter:
- qs = filter(qs, q)
-
- # order
- if self.sort == 'asc':
- qs = qs.order_by('date', 'id')
- else:
- qs = qs.order_by('-date', '-id')
-
- # exclude
- qs = qs.exclude(id = exclude)
-
- self.qs = qs
- return qs
-
-
diff --git a/website/views.py b/website/views.py
index 2c2f93b..f8ae946 100644
--- a/website/views.py
+++ b/website/views.py
@@ -1,14 +1,18 @@
from django.shortcuts import render
-from django.utils import timezone
+from django.template.loader import render_to_string
from django.views.generic import ListView
from django.views.generic import DetailView
from django.core import serializers
from django.utils.translation import ugettext as _, ugettext_lazy
from website.models import *
+from website.routes import *
class PostListView (ListView):
+ """
+ List view for posts and children
+ """
class Query:
"""
Request availables parameters
@@ -32,19 +36,18 @@ class PostListView (ListView):
template_name = 'website/list.html'
allow_empty = True
+ model = None
query = None
fields = [ 'date', 'time', 'image', 'title', 'content' ]
- route = None
- model = None
-
def __init__ (self, *args, **kwargs):
- super(PostListView, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
if self.query:
self.query = Query(self.query)
def get_queryset (self):
- qs = self.route.get_queryset(self.request, **self.kwargs)
+ route = self.kwargs['route']
+ qs = route.get_queryset(self.request, **self.kwargs)
qs = qs.filter(public = True)
query = self.query or PostListView.Query(self.request.GET)
@@ -59,7 +62,7 @@ class PostListView (ListView):
def get_context_data (self, **kwargs):
- context = super(PostListView, self).get_context_data(**kwargs)
+ context = super().get_context_data(**kwargs)
context.update({
'list': self
})
@@ -67,4 +70,100 @@ class PostListView (ListView):
return context
+class PostDetailView (DetailView):
+ """
+ Detail view for posts and children
+ """
+ template_name = 'website/detail.html'
+ sections = None
+
+ def __init__ (self, sections = None, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def get_queryset (self, **kwargs):
+ if self.model:
+ return super().get_queryset(**kwargs).filter(public = True)
+ return []
+
+ def get_object (self, **kwargs):
+ if self.model:
+ object = super().get_object(**kwargs)
+ if object.public:
+ return object
+ return None
+
+ def get_context_data (self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context.update({
+ 'sections': [
+ section.get(self, self.request, object = self.object)
+ for section in self.sections
+ ]
+ })
+ return context
+
+
+class Section (DetailView):
+ """
+ Base class for sections. Sections are view that can be used in detail view
+ in order to have extra content about a post.
+ """
+ model = None
+ template_name = 'website/section.html'
+ classes = ''
+ title = ''
+ header = ''
+ bottom = ''
+
+ def get_context_data (self, **kwargs):
+ context = super().get_context_date(**kwargs)
+ context.update({
+ 'title': self.title,
+ 'header': self.header,
+ 'bottom': self.bottom,
+ 'classes': self.classes,
+ })
+
+ def get (self, request, **kwargs):
+ self.object = kwargs.get('object')
+ context = self.get_context_data(**kwargs)
+ return render_to_string(self.template_name, context)
+
+
+class ViewSet:
+ """
+ A ViewSet is a class helper that groups detail and list views that can be
+ used to generate views and routes given a model and a name used for the
+ routing.
+ """
+ model = None
+ name = ''
+
+ list_view = PostListView
+ list_routes = []
+
+ detail_view = PostDetailView
+ detail_sections = []
+
+ def __init__ (self):
+ if not self.name:
+ self.name = self.model._meta.verbose_name_plural
+
+ self.detail_sections = [
+ section.as_view(model = self.model)
+ for section in self.detail_sections
+ ]
+ self.detail_view = self.detail_view.as_view(
+ model = self.model,
+ sections = self.detail_sections
+ )
+ self.list_view = self.list_view.as_view(
+ model = self.model
+ )
+
+ self.routes = [ route(self.model, self.list_view, base_name = self.name)
+ for route in self.list_routes ] + \
+ [ DetailRoute(self.model, self.detail_view,
+ base_name = self.name) ]
+