diff --git a/cms/routes.py b/cms/routes.py index d890cca..b09a2b8 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -12,14 +12,14 @@ class Router: self.registry.append(route) def register_set (self, view_set): - for route in view_set.routes: - self.register(route) + for url in view_set.urls: + self.register(url) def unregister (self, route): self.registry.remove(route) def get_urlpatterns (self): - return [ route.get_url() for route in self.registry ] + return [ url for url in self.registry ] class Route: @@ -33,125 +33,113 @@ class Route: The given view is considered as a django class view, and has view_ """ - model = None # model routed here - view = None # view class to call - view_kwargs = None # arguments passed to view at creation of the urls + name = None # route name + url_args = [] # arguments passed from the url [ (name : regex),... ] - class Meta: - name = None # route name - 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): + @classmethod + def get_queryset (cl, model, request, **kwargs): """ Called by the view to get the queryset when it is needed """ 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 """ pass - def get_url (self): - pattern = '^{}/{}'.format(self.base_name, self.Meta.name) - if self._meta['url_args']: + + @classmethod + 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([ '(?P<{}>{}){}'.format( arg, expr, (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 += '/?$' kwargs = { - 'route': self, + 'route': cl, } - if self.view_kwargs: - kwargs.update(self.view_kwargs) + if view_kwargs: + kwargs.update(view_kwargs) - return url(pattern, self.view, kwargs = kwargs, - name = self.base_name + '_' + self.Meta.name) + return url(pattern, view, kwargs = kwargs, + name = base_name + '_' + cl.name) class DetailRoute (Route): - class Meta: - name = 'detail' - is_list = False - url_args = [ - ('pk', '[0-9]+'), - ('slug', '(\w|-|_)+', True), - ] + name = 'detail' + url_args = [ + ('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 Meta: - name = 'all' - is_list = True + name = 'all' - def get_queryset (self, request, **kwargs): - return self.model.objects.all() + @classmethod + def get_queryset (cl, model, request, **kwargs): + return model.objects.all() class ThreadRoute (Route): - class Meta: - name = 'thread' - is_list = True - url_args = [ - ('pk', '[0-9]+'), - ] + name = 'thread' + url_args = [ + ('pk', '[0-9]+'), + ] - def get_queryset (self, request, **kwargs): - return self.model.objects.filter(thread__pk = int(kwargs['pk'])) + @classmethod + def get_queryset (cl, model, request, pk, **kwargs): + return model.objects.filter(thread__pk = int(pk)) class DateRoute (Route): - class Meta: - name = 'date' - is_list = True - url_args = [ - ('year', '[0-9]{4}'), - ('month', '[0-9]{2}'), - ('day', '[0-9]{1,2}'), - ] + name = 'date' + url_args = [ + ('year', '[0-9]{4}'), + ('month', '[0-9]{2}'), + ('day', '[0-9]{1,2}'), + ] - def get_queryset (self, request, **kwargs): - return self.model.objects.filter( - date__year = int(kwargs['year']), - date__month = int(kwargs['month']), - date__day = int(kwargs['day']), + @classmethod + def get_queryset (cl, model, request, year, month, day, **kwargs): + return model.objects.filter( + date__year = int(year), + date__month = int(month), + date__day = int(day), ) class SearchRoute (Route): - class Meta: - name = 'search' - is_list = True + name = 'search' - def get_queryset (self, request, **kwargs): + @classmethod + def get_queryset (cl, model, request, **kwargs): q = request.GET.get('q') or '' - qs = self.model.objects + qs = model.objects 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 else: qs = r diff --git a/cms/views.py b/cms/views.py index 9078248..64d790f 100644 --- a/cms/views.py +++ b/cms/views.py @@ -8,63 +8,6 @@ from django.utils.translation import ugettext as _, ugettext_lazy 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): """ List view for posts and children @@ -94,6 +37,9 @@ class PostListView (ListView): model = None query = None + classes = '' + title = '' + embed = False fields = [ 'date', 'time', 'image', 'title', 'content' ] def __init__ (self, *args, **kwargs): @@ -101,30 +47,45 @@ class PostListView (ListView): if 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): - route = self.kwargs['route'] - qs = route.get_queryset(self.request, **self.kwargs) + qs = self.route.get_queryset(self.model, self.request, **self.kwargs) qs = qs.filter(public = True) query = self.query or PostListView.Query(self.request.GET) if query.exclude: qs = qs.exclude(id = int(exclude)) + if query.embed: + self.embed = True + if query.order == 'asc': qs.order_by('date', 'id') else: qs.order_by('-date', '-id') return qs - def get_context_data (self, **kwargs): context = super().get_context_data(**kwargs) context.update({ - 'list': self + 'list': self, + 'title': self.get_title(), + 'classes': self.classes, }) 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): """ @@ -153,7 +114,7 @@ class PostDetailView (DetailView): context = super().get_context_data(**kwargs) context.update({ 'sections': [ - section.get(self, self.request, object = self.object) + section.get(self.request, object = self.object) for section in self.sections ] }) @@ -186,8 +147,85 @@ class ViewSet: 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 ] + \ - [ 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 diff --git a/website/views.py b/website/views.py index 8098888..1965572 100644 --- a/website/views.py +++ b/website/views.py @@ -34,3 +34,4 @@ class ScheduleSection (ListSection): ] +