work on postlistsection, rework on routes

This commit is contained in:
bkfox 2015-10-01 19:24:52 +02:00
parent 17aa33fe04
commit 2af9cf8b13
3 changed files with 167 additions and 140 deletions

View File

@ -12,14 +12,14 @@ class Router:
self.registry.append(route) self.registry.append(route)
def register_set (self, view_set): def register_set (self, view_set):
for route in view_set.routes: for url in view_set.urls:
self.register(route) self.register(url)
def unregister (self, route): def unregister (self, route):
self.registry.remove(route) self.registry.remove(route)
def get_urlpatterns (self): def get_urlpatterns (self):
return [ route.get_url() for route in self.registry ] return [ url for url in self.registry ]
class Route: class Route:
@ -33,125 +33,113 @@ class Route:
The given view is considered as a django class view, and has view_ The given view is considered as a django class view, and has view_
""" """
model = None # model routed here name = None # route name
view = None # view class to call url_args = [] # arguments passed from the url [ (name : regex),... ]
view_kwargs = None # arguments passed to view at creation of the urls
class Meta: @classmethod
name = None # route name def get_queryset (cl, model, request, **kwargs):
is_list = False # route is for a list
url_args = [] # arguments passed from the url [ (name : regex),... ]
def __init__ (self, model, view, view_kwargs = None):
self.model = model
self.view = view
self.view_kwargs = view_kwargs
self.embed = False
_meta = {}
_meta.update(Route.Meta.__dict__)
_meta.update(self.Meta.__dict__)
self._meta = _meta
self.base_name = model._meta.verbose_name_plural.lower()
def get_queryset (self, request, **kwargs):
""" """
Called by the view to get the queryset when it is needed Called by the view to get the queryset when it is needed
""" """
pass pass
def get (self, request, **kwargs): @classmethod
def get_object (cl, model, request, **kwargs):
""" """
Called by the view to get the object when it is needed Called by the view to get the object when it is needed
""" """
pass pass
def get_url (self):
pattern = '^{}/{}'.format(self.base_name, self.Meta.name) @classmethod
if self._meta['url_args']: def get_title (cl, model, request, **kwargs):
return ''
@classmethod
def as_url (cl, model, view, view_kwargs = None):
base_name = model._meta.verbose_name_plural.lower()
pattern = '^{}/{}'.format(base_name, cl.name)
if cl.url_args:
url_args = '/'.join([ url_args = '/'.join([
'(?P<{}>{}){}'.format( '(?P<{}>{}){}'.format(
arg, expr, arg, expr,
(optional and optional[0] and '?') or '' (optional and optional[0] and '?') or ''
) )
for arg, expr, *optional in self._meta['url_args'] for arg, expr, *optional in cl.url_args
]) ])
pattern += '/' + url_args pattern += '/' + url_args
pattern += '/?$' pattern += '/?$'
kwargs = { kwargs = {
'route': self, 'route': cl,
} }
if self.view_kwargs: if view_kwargs:
kwargs.update(self.view_kwargs) kwargs.update(view_kwargs)
return url(pattern, self.view, kwargs = kwargs, return url(pattern, view, kwargs = kwargs,
name = self.base_name + '_' + self.Meta.name) name = base_name + '_' + cl.name)
class DetailRoute (Route): class DetailRoute (Route):
class Meta: name = 'detail'
name = 'detail' url_args = [
is_list = False ('pk', '[0-9]+'),
url_args = [ ('slug', '(\w|-|_)+', True),
('pk', '[0-9]+'), ]
('slug', '(\w|-|_)+', True),
]
def get (self, request, **kwargs):
return self.model.objects.get(pk = int(kwargs['pk'])) @classmethod
def get_object (cl, model, request, pk, **kwargs):
return model.objects.get(pk = int(pk))
class AllRoute (Route): class AllRoute (Route):
class Meta: name = 'all'
name = 'all'
is_list = True
def get_queryset (self, request, **kwargs): @classmethod
return self.model.objects.all() def get_queryset (cl, model, request, **kwargs):
return model.objects.all()
class ThreadRoute (Route): class ThreadRoute (Route):
class Meta: name = 'thread'
name = 'thread' url_args = [
is_list = True ('pk', '[0-9]+'),
url_args = [ ]
('pk', '[0-9]+'),
]
def get_queryset (self, request, **kwargs): @classmethod
return self.model.objects.filter(thread__pk = int(kwargs['pk'])) def get_queryset (cl, model, request, pk, **kwargs):
return model.objects.filter(thread__pk = int(pk))
class DateRoute (Route): class DateRoute (Route):
class Meta: name = 'date'
name = 'date' url_args = [
is_list = True ('year', '[0-9]{4}'),
url_args = [ ('month', '[0-9]{2}'),
('year', '[0-9]{4}'), ('day', '[0-9]{1,2}'),
('month', '[0-9]{2}'), ]
('day', '[0-9]{1,2}'),
]
def get_queryset (self, request, **kwargs): @classmethod
return self.model.objects.filter( def get_queryset (cl, model, request, year, month, day, **kwargs):
date__year = int(kwargs['year']), return model.objects.filter(
date__month = int(kwargs['month']), date__year = int(year),
date__day = int(kwargs['day']), date__month = int(month),
date__day = int(day),
) )
class SearchRoute (Route): class SearchRoute (Route):
class Meta: name = 'search'
name = 'search'
is_list = True
def get_queryset (self, request, **kwargs): @classmethod
def get_queryset (cl, model, request, **kwargs):
q = request.GET.get('q') or '' q = request.GET.get('q') or ''
qs = self.model.objects qs = model.objects
for search_field in model.search_fields or []: for search_field in model.search_fields or []:
r = self.model.objects.filter(**{ search_field + '__icontains': q }) r = model.objects.filter(**{ search_field + '__icontains': q })
if qs: qs = qs | r if qs: qs = qs | r
else: qs = r else: qs = r

View File

@ -8,63 +8,6 @@ from django.utils.translation import ugettext as _, ugettext_lazy
import cms.routes as routes import cms.routes as routes
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.
"""
template_name = 'cms/section.html'
classes = ''
title = ''
content = ''
header = ''
bottom = ''
def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'title': self.title,
'header': self.header,
'content': self.content,
'bottom': self.bottom,
'classes': self.classes,
})
return context
def get (self, parent, request, object = None, **kwargs):
print(type(object))
self.object = object
context = self.get_context_data(**kwargs)
return render_to_string(self.template_name, context)
class ListSection (Section):
"""
Section to render list. The context item 'object_list' is used as list of
items to render.
"""
class Item:
icon = None
title = None
text = None
def __init__ (self, icon, title = None, text = None):
self.icon = icon
self.title = title
self.text = text
template_name = 'cms/section_list.html'
def get_object_list (self):
return []
def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs)
context['classes'] += ' section_list'
context['object_list'] = self.get_object_list()
return context
class PostListView (ListView): class PostListView (ListView):
""" """
List view for posts and children List view for posts and children
@ -94,6 +37,9 @@ class PostListView (ListView):
model = None model = None
query = None query = None
classes = ''
title = ''
embed = False
fields = [ 'date', 'time', 'image', 'title', 'content' ] fields = [ 'date', 'time', 'image', 'title', 'content' ]
def __init__ (self, *args, **kwargs): def __init__ (self, *args, **kwargs):
@ -101,30 +47,45 @@ class PostListView (ListView):
if self.query: if self.query:
self.query = Query(self.query) self.query = Query(self.query)
def dispatch (self, request, *args, **kwargs):
self.route = self.kwargs.get('route')
return super().dispatch(request, *args, **kwargs)
def get_queryset (self): def get_queryset (self):
route = self.kwargs['route'] qs = self.route.get_queryset(self.model, self.request, **self.kwargs)
qs = route.get_queryset(self.request, **self.kwargs)
qs = qs.filter(public = True) qs = qs.filter(public = True)
query = self.query or PostListView.Query(self.request.GET) query = self.query or PostListView.Query(self.request.GET)
if query.exclude: if query.exclude:
qs = qs.exclude(id = int(exclude)) qs = qs.exclude(id = int(exclude))
if query.embed:
self.embed = True
if query.order == 'asc': if query.order == 'asc':
qs.order_by('date', 'id') qs.order_by('date', 'id')
else: else:
qs.order_by('-date', '-id') qs.order_by('-date', '-id')
return qs return qs
def get_context_data (self, **kwargs): def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ context.update({
'list': self 'list': self,
'title': self.get_title(),
'classes': self.classes,
}) })
return context return context
def get_title (self):
if self.title:
return self.title
title = self.route and self.route.get_title(self.model, self.request,
**self.kwargs)
return title
class PostDetailView (DetailView): class PostDetailView (DetailView):
""" """
@ -153,7 +114,7 @@ class PostDetailView (DetailView):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context.update({ context.update({
'sections': [ 'sections': [
section.get(self, self.request, object = self.object) section.get(self.request, object = self.object)
for section in self.sections for section in self.sections
] ]
}) })
@ -186,8 +147,85 @@ class ViewSet:
model = self.model model = self.model
) )
self.routes = [ route(self.model, self.list_view) self.urls = [ route.as_url(self.model, self.list_view)
for route in self.list_routes ] + \ for route in self.list_routes ] + \
[ routes.DetailRoute(self.model, self.detail_view ) ] [ routes.DetailRoute.as_url(self.model, self.detail_view ) ]
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.
"""
template_name = 'cms/section.html'
classes = ''
title = ''
content = ''
header = ''
bottom = ''
def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({
'title': self.title,
'header': self.header,
'content': self.content,
'bottom': self.bottom,
'classes': self.classes,
})
return context
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 ListSection (Section):
"""
Section to render list. The context item 'object_list' is used as list of
items to render.
"""
class Item:
icon = None
title = None
text = None
def __init__ (self, icon, title = None, text = None):
self.icon = icon
self.title = title
self.text = text
template_name = 'cms/section_list.html'
def get_object_list (self):
return []
def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs)
context['classes'] += ' section_list'
context['object_list'] = self.get_object_list()
return context
class PostListSection (PostListView):
route = None
model = None
embed = True
def __init__ (self, *args, **kwargs):
super().__init__(*args, **kwargs)
def get_kwargs (self, request, **kwargs):
return kwargs
def dispatch (self, request, *args, **kwargs):
kwargs = self.get_kwargs(kwargs)
# TODO: to_string
return super().dispatch(request, *args, **kwargs)
# TODO:
# - get_title: pass object / queryset

View File

@ -34,3 +34,4 @@ class ScheduleSection (ListSection):
] ]