diff --git a/cms/models.py b/cms/models.py index c068de2..bf39b18 100644 --- a/cms/models.py +++ b/cms/models.py @@ -16,34 +16,6 @@ from taggit.managers import TaggableManager from aircox.cms import routes -class ProxyPost: - """ - Class used to simulate a Post model when it is required to render an - item linked to a Post but that is not that itself. This is to ensure - the right attributes are set. - """ - detail_url = None - date = None - image = None - title = None - content = None - - def __init__(self, post = None, **kwargs): - if post: - self.update_empty(post) - self.__dict__.update(**kwargs) - - def update_empty(self, thread): - """ - Update empty fields using thread object - """ - for i in ('date', 'image', 'title', 'content'): - if not getattr(self, i): - setattr(self, i, getattr(thread, i)) - if not self.detail_url: - self.detail_url = thread.detail_url() - - class Comment(models.Model): thread_type = models.ForeignKey( ContentType, @@ -134,12 +106,6 @@ class Post (models.Model): search_fields = [ 'title', 'content' ] - def as_proxy(self): - """ - Return a ProxyPost instance using this post - """ - return ProxyPost(self) - @classmethod def children_of(cl, thread, queryset = None): """ diff --git a/cms/sections.py b/cms/sections.py index 9dc82e5..f9c6e15 100644 --- a/cms/sections.py +++ b/cms/sections.py @@ -6,6 +6,7 @@ import re from django.templatetags.static import static from django.template.loader import render_to_string from django.views.generic.base import View +from django.contrib import messages from django.utils.html import escape from django.utils.translation import ugettext as _, ugettext_lazy @@ -214,16 +215,18 @@ class List(Section): class Comments(List): """ - Section used to render comment form and comments list. It only render - the form if the comments are enabled on the target object. - - It does not handle comment posts, this is directly done at the - level of the detail view. + Section used to render comment form and comments list. It renders the + form and comments, and save them. """ css_class="comments" truncate = 0 fields = [ 'date', 'time', 'author', 'content' ] + success_message = ( _('Your message is awaiting for approval'), + _('Your message has been published') ) + error_message = _('There was an error while saving your post. ' + 'Please check errors below') + def get_object_list(self): qs = self.object.get_comments().filter(published=True). \ order_by('-date') @@ -232,16 +235,37 @@ class Comments(List): for comment in qs ] def get_context_data(self): - context = super().get_context_data() post = self.object + if hasattr(post, 'allow_comments') and post.allow_comments: + comment_form = (self.comment_form or CommentForm()) + else: + comment_form = None + + context = super().get_context_data() context.update({ 'base_template': 'aircox/cms/comments.html', - 'comment_form': CommentForm() \ - if hasattr(post, 'allow_comments') and post.allow_comments \ - else None + 'comment_form': comment_form, }) + + self.comment_form = None return context + def post(self, view, request, object): + """ + Forward data to this view + """ + comment_form = CommentForm(request.POST) + if comment_form.is_valid(): + comment = comment_form.save(commit=False) + comment.thread = self.object + comment.published = view.website.auto_publish_comments + comment.save() + + messages.success(request, self.success_message[comment.published], + fail_silently=True) + else: + messages.error(request, self.error_message, fail_silently=True) + self.comment_form = comment_form class Menu(Section): template_name = 'aircox/cms/section.html' @@ -249,7 +273,6 @@ class Menu(Section): classes = '' attrs = '' name = '' - enabled = True position = '' # top, left, bottom, right, header, footer, page_top, page_bottom sections = None diff --git a/cms/templates/aircox/cms/website.html b/cms/templates/aircox/cms/website.html index 7c388db..660e7ed 100644 --- a/cms/templates/aircox/cms/website.html +++ b/cms/templates/aircox/cms/website.html @@ -34,6 +34,16 @@
{% endif %} + {% if messages %} + + {% endif %} + {% block pre_title %} {% endblock %}

diff --git a/cms/views.py b/cms/views.py index 9876f9b..2077c5c 100644 --- a/cms/views.py +++ b/cms/views.py @@ -3,11 +3,10 @@ from django.template.loader import render_to_string from django.views.generic import ListView, DetailView from django.views.generic.base import View from django.utils.translation import ugettext as _, ugettext_lazy +from django.contrib import messages from django.http import Http404 -from honeypot.decorators import verify_honeypot_value - -from aircox.cms.forms import CommentForm +import aircox.cms.sections as sections class PostBaseView: @@ -31,10 +30,7 @@ class PostBaseView: object = self.object if hasattr(self, 'object') else None context['menus'] = { k: v.get(self.request, object = object, **kwargs) - for k, v in { - k: self.website.get_menu(k) - for k in self.website.menu_layouts - }.items() if v + for k, v in self.website.menus.items() } context['view'] = self return context @@ -128,6 +124,7 @@ class PostDetailView(DetailView, PostBaseView): template_name = 'aircox/cms/detail.html' sections = [] + comments = None def __init__(self, sections = None, *args, **kwargs): super().__init__(*args, **kwargs) @@ -162,17 +159,13 @@ class PostDetailView(DetailView, PostBaseView): """ Handle new comments """ + if not self.comments: + for section in self.sections: + if issubclass(type(section), sections.Comments): + self.comments = section + self.object = self.get_object() - if not self.object: - raise Http404() - - comment_form = CommentForm(request.POST) - if not comment_form.is_valid() or verify_honeypot_value(request, 'hp_website'): - raise Http404() - comment = comment_form.save(commit=False) - comment.thread = self.object - comment.save() - + self.comments.post(self, request, object) return self.get(request, *args, **kwargs) diff --git a/cms/website.py b/cms/website.py index e119088..ece4722 100644 --- a/cms/website.py +++ b/cms/website.py @@ -2,25 +2,41 @@ import aircox.cms.routes as routes import aircox.cms.views as views class Website: + """ + Describe a website and all its settings that are used for its rendering. + """ + # metadata name = '' domain = '' - description = 'An aircox website' # public description (used in meta info) - tags = 'aircox,radio,music' # public keywords (used in meta info) + description = 'An aircox website' + tags = 'aircox,radio,music' - styles = '' # relative url to stylesheet file - menus = None # list of menus - menu_layouts = ['top', 'left', # available positions - 'right', 'bottom', - 'header', 'footer'] - router = None + # rendering + styles = '' + menus = None + + # user interaction + allow_comments = True + auto_publish_comments = False + + # components urls = [] registry = {} - def __init__ (self, **kwargs): + def __init__ (self, menus = None, **kwargs): + """ + * menus: a list of menus to add to the website + """ self.registry = {} self.urls = [] + self.menus = {} self.__dict__.update(kwargs) + if menus: + for menu in menus: + self.set_menu(menu) + + def name_of_model (self, model): for name, _model in self.registry.items(): if model is _model: @@ -67,6 +83,8 @@ class Website: self.registry[name] = model def register (self, name, model, sections = None, routes = None, + list_view = views.PostListView, + detail_view = views.PostDetailView, list_kwargs = {}, detail_kwargs = {}): """ Register a detail and list view for a given model, using @@ -86,22 +104,20 @@ class Website: **list_kwargs ) + def set_menu (self, menu): + """ + Set a menu, and remove any previous menu at the same position + """ + if menu.position in ('footer','header'): + menu.tag = menu.position + elif menu.position in ('left', 'right'): + menu.tag = 'side' + self.menus[menu.position] = menu + def get_menu (self, position): """ Get an enabled menu by its position """ - for menu in self.menus: - if menu.enabled and menu.position == position: - self.check_menu_tag(menu) - return menu - - def check_menu_tag (self, menu): - """ - Update menu tag if it is a footer or a header - """ - if menu.position in ('footer','header'): - menu.tag = menu.position - if menu.position in ('left', 'right'): - menu.tag = 'side' + return self.menus.get(position)