"""
Define different Section css_class that can be used by views.Sections;
"""
import re
from django.template.loader import render_to_string
from django.views.generic.base import View
from django.templatetags.static import static
from django.http import HttpResponse
from django.contrib import messages
from django.utils.html import escape
from django.utils.translation import ugettext as _, ugettext_lazy
from honeypot.decorators import check_honeypot
from aircox.cms.forms import CommentForm
class Viewable:
"""
Describe a view that is still usable as a class after as_view() has
been called.
"""
@classmethod
def as_view (cl, *args, **kwargs):
"""
Similar to View.as_view, but instead, wrap a constructor of the
given class that is used as is.
"""
def func(**kwargs_):
if kwargs_:
kwargs.update(kwargs_)
instance = cl(*args, **kwargs)
return instance
return func
class Sections(Viewable, list):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for i, section in enumerate(self):
if callable(section) or type(section) == type:
self[i] = section()
def render(self, *args, **kwargs):
return ''.join([
section.render(*args, **kwargs)
for section in self
])
def filter(self, predicate):
return [ section for section in self if predicate(section) ]
class Section(Viewable, View):
"""
On the contrary to Django's views, we create an instance of the view
only once, when the server is run.
Attributes are not changed once they have been set, and are related
to Section configuration/rendering. However, some data are considered
as temporary, and are reset at each rendering, using given arguments.
When get_context_data returns None, returns an empty string
! Important Note: values given for rendering are considered as safe
HTML in templates.
Attributes:
* template_name: template to use for rendering
* tag: container's tags
* name: set name/id of the section container
* css_class: css classes of the container
* attr: HTML attributes of the container
* title: title of the section
* header: header of the section
* footer: footer of the section
"""
template_name = 'aircox/cms/website.html'
tag = 'div'
name = ''
css_class = ''
attrs = None
title = ''
header = ''
footer = ''
request = None
object = None
kwargs = None
def add_css_class(self, css_class):
if self.css_class:
if css_class not in self.css_class.split(' '):
self.css_class += ' ' + css_class
else:
self.css_class = css_class
def __init__ (self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.add_css_class('section')
if type(self) != Section:
self.add_css_class('section_' + type(self).__name__.lower())
if not self.attrs:
self.attrs = {}
if self.name:
self.attrs['name'] = self.name
self.attrs['id'] = self.name
def get_content(self):
return ''
def get_context_data(self, request = None, object = None, **kwargs):
if request: self.request = request
if object: self.object = object
if kwargs: self.kwargs = kwargs
return {
'view': self,
'tag': self.tag,
'css_class': self.css_class,
'attrs': self.attrs,
'title': self.title,
'header': self.header,
'footer': self.footer,
'content': self.get_content(),
'object': self.object,
'embed': True,
}
def render(self, request, object=None, context_only=False, **kwargs):
context = self.get_context_data(request=request, object=object, **kwargs)
if context_only:
return context
if not context:
return ''
context['embed'] = True
return render_to_string(self.template_name, context, request=request)
class Image(Section):
"""
Render an image using the relative url or relative to self.object.
Attributes:
* url: relative image url
* rel_attr: name of the attribute of self.object to use
"""
url = None
rel_attr = 'image'
def get_content(self, **kwargs):
if self.url is None:
image = getattr(self.object, self.rel_attr)
return ''.format(image.url) if image else ''
return '
'.format(static(self.url))
class Content(Section):
"""
Render content using the self.content or relative to self.object.
Attributes:
* content: raw HTML code to render
* rel_attr: name of the attribute of self.object to use
* re_image_attr: if true and there is an image on the current object,
render the object's image
"""
content = None
rel_attr = 'content'
rel_image_attr = 'image'
def get_content(self):
if self.content is None:
content = getattr(self.object, self.rel_attr)
content = escape(content)
content = re.sub(r'(^|\n\n)((\n?[^\n])+)', r'
\2
', content) content = re.sub(r'\n', r'