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
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):
"""

View File

@ -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

View File

@ -34,6 +34,16 @@
<main>
{% 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 %}
{% endblock %}
<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.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)

View File

@ -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)