remove old ProxyPost; comments posting managed by sections.Comments; support for messages; change how menus works in Website

This commit is contained in:
bkfox 2016-05-27 00:45:50 +02:00
parent 7c89f84b34
commit 94b9aab006
5 changed files with 91 additions and 83 deletions

View File

@ -16,34 +16,6 @@ from taggit.managers import TaggableManager
from aircox.cms import routes 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): class Comment(models.Model):
thread_type = models.ForeignKey( thread_type = models.ForeignKey(
ContentType, ContentType,
@ -134,12 +106,6 @@ class Post (models.Model):
search_fields = [ 'title', 'content' ] search_fields = [ 'title', 'content' ]
def as_proxy(self):
"""
Return a ProxyPost instance using this post
"""
return ProxyPost(self)
@classmethod @classmethod
def children_of(cl, thread, queryset = None): def children_of(cl, thread, queryset = None):
""" """

View File

@ -6,6 +6,7 @@ import re
from django.templatetags.static import static from django.templatetags.static import static
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.views.generic.base import View from django.views.generic.base import View
from django.contrib import messages
from django.utils.html import escape from django.utils.html import escape
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
@ -214,16 +215,18 @@ class List(Section):
class Comments(List): class Comments(List):
""" """
Section used to render comment form and comments list. It only render Section used to render comment form and comments list. It renders the
the form if the comments are enabled on the target object. form and comments, and save them.
It does not handle comment posts, this is directly done at the
level of the detail view.
""" """
css_class="comments" css_class="comments"
truncate = 0 truncate = 0
fields = [ 'date', 'time', 'author', 'content' ] 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): def get_object_list(self):
qs = self.object.get_comments().filter(published=True). \ qs = self.object.get_comments().filter(published=True). \
order_by('-date') order_by('-date')
@ -232,16 +235,37 @@ class Comments(List):
for comment in qs ] for comment in qs ]
def get_context_data(self): def get_context_data(self):
context = super().get_context_data()
post = self.object 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({ context.update({
'base_template': 'aircox/cms/comments.html', 'base_template': 'aircox/cms/comments.html',
'comment_form': CommentForm() \ 'comment_form': comment_form,
if hasattr(post, 'allow_comments') and post.allow_comments \
else None
}) })
self.comment_form = None
return context 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): class Menu(Section):
template_name = 'aircox/cms/section.html' template_name = 'aircox/cms/section.html'
@ -249,7 +273,6 @@ class Menu(Section):
classes = '' classes = ''
attrs = '' attrs = ''
name = '' name = ''
enabled = True
position = '' # top, left, bottom, right, header, footer, page_top, page_bottom position = '' # top, left, bottom, right, header, footer, page_top, page_bottom
sections = None sections = None

View File

@ -34,6 +34,16 @@
<main> <main>
{% endif %} {% endif %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% block pre_title %} {% block pre_title %}
{% endblock %} {% endblock %}
<h1> <h1>

View File

@ -3,11 +3,10 @@ from django.template.loader import render_to_string
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from django.views.generic.base import View from django.views.generic.base import View
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
from django.contrib import messages
from django.http import Http404 from django.http import Http404
from honeypot.decorators import verify_honeypot_value import aircox.cms.sections as sections
from aircox.cms.forms import CommentForm
class PostBaseView: class PostBaseView:
@ -31,10 +30,7 @@ class PostBaseView:
object = self.object if hasattr(self, 'object') else None object = self.object if hasattr(self, 'object') else None
context['menus'] = { context['menus'] = {
k: v.get(self.request, object = object, **kwargs) k: v.get(self.request, object = object, **kwargs)
for k, v in { for k, v in self.website.menus.items()
k: self.website.get_menu(k)
for k in self.website.menu_layouts
}.items() if v
} }
context['view'] = self context['view'] = self
return context return context
@ -128,6 +124,7 @@ class PostDetailView(DetailView, PostBaseView):
template_name = 'aircox/cms/detail.html' template_name = 'aircox/cms/detail.html'
sections = [] sections = []
comments = None
def __init__(self, sections = None, *args, **kwargs): def __init__(self, sections = None, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -162,17 +159,13 @@ class PostDetailView(DetailView, PostBaseView):
""" """
Handle new comments 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() self.object = self.get_object()
if not self.object: self.comments.post(self, request, 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()
return self.get(request, *args, **kwargs) return self.get(request, *args, **kwargs)

View File

@ -2,25 +2,41 @@ import aircox.cms.routes as routes
import aircox.cms.views as views import aircox.cms.views as views
class Website: class Website:
"""
Describe a website and all its settings that are used for its rendering.
"""
# metadata
name = '' name = ''
domain = '' domain = ''
description = 'An aircox website' # public description (used in meta info) description = 'An aircox website'
tags = 'aircox,radio,music' # public keywords (used in meta info) tags = 'aircox,radio,music'
styles = '' # relative url to stylesheet file # rendering
menus = None # list of menus styles = ''
menu_layouts = ['top', 'left', # available positions menus = None
'right', 'bottom',
'header', 'footer'] # user interaction
router = None allow_comments = True
auto_publish_comments = False
# components
urls = [] urls = []
registry = {} registry = {}
def __init__ (self, **kwargs): def __init__ (self, menus = None, **kwargs):
"""
* menus: a list of menus to add to the website
"""
self.registry = {} self.registry = {}
self.urls = [] self.urls = []
self.menus = {}
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
if menus:
for menu in menus:
self.set_menu(menu)
def name_of_model (self, model): def name_of_model (self, model):
for name, _model in self.registry.items(): for name, _model in self.registry.items():
if model is _model: if model is _model:
@ -67,6 +83,8 @@ class Website:
self.registry[name] = model self.registry[name] = model
def register (self, name, model, sections = None, routes = None, def register (self, name, model, sections = None, routes = None,
list_view = views.PostListView,
detail_view = views.PostDetailView,
list_kwargs = {}, detail_kwargs = {}): list_kwargs = {}, detail_kwargs = {}):
""" """
Register a detail and list view for a given model, using Register a detail and list view for a given model, using
@ -86,22 +104,20 @@ class Website:
**list_kwargs **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): def get_menu (self, position):
""" """
Get an enabled menu by its position Get an enabled menu by its position
""" """
for menu in self.menus: return self.menus.get(position)
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'