forked from rc/aircox
		
	clean up a bit
This commit is contained in:
		@ -12,6 +12,36 @@ from django.dispatch import receiver
 | 
			
		||||
 | 
			
		||||
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 Post (models.Model):
 | 
			
		||||
    """
 | 
			
		||||
@ -64,6 +94,14 @@ class Post (models.Model):
 | 
			
		||||
        blank = True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    search_fields = [ 'title', 'content' ]
 | 
			
		||||
 | 
			
		||||
    def get_proxy(self):
 | 
			
		||||
        """
 | 
			
		||||
        Return a ProxyPost instance using this post
 | 
			
		||||
        """
 | 
			
		||||
        return ProxyPost(self)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def children_of(cl, thread, queryset = None):
 | 
			
		||||
        """
 | 
			
		||||
@ -77,10 +115,15 @@ class Post (models.Model):
 | 
			
		||||
                              thread_type__pk = thread_type.id)
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
    def detail_url (self):
 | 
			
		||||
        return reverse(self._website.name_of_model(self.__class__) + '_detail',
 | 
			
		||||
                       kwargs = { 'pk': self.pk,
 | 
			
		||||
                                  'slug': slugify(self.title) })
 | 
			
		||||
    def detail_url(self):
 | 
			
		||||
        return self.route_url(routes.DetailRoute,
 | 
			
		||||
                              { 'pk': self.pk, 'slug': slugify(self.title) })
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def route_url(cl, route, kwargs = None):
 | 
			
		||||
        name = cl._website.name_of_model(cl)
 | 
			
		||||
        name = route.get_view_name(name)
 | 
			
		||||
        return reverse(name, kwargs = kwargs)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
@ -170,6 +213,7 @@ class RelatedPostBase (models.base.ModelBase):
 | 
			
		||||
        }.items() if not attrs.get(x) })
 | 
			
		||||
 | 
			
		||||
        model = super().__new__(cl, name, bases, attrs)
 | 
			
		||||
        print(model, model.related)
 | 
			
		||||
        cl.register(rel.model, model)
 | 
			
		||||
 | 
			
		||||
        # name clashes
 | 
			
		||||
@ -317,7 +361,7 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
			
		||||
        super().__init__(*kargs, **kwargs)
 | 
			
		||||
        # we use this method for sync, in order to avoid intrusive code on other
 | 
			
		||||
        # applications, e.g. using signals.
 | 
			
		||||
        if self._relation.rel_to_post:
 | 
			
		||||
        if self.pk and self._relation.rel_to_post:
 | 
			
		||||
            self.rel_to_post(save = False)
 | 
			
		||||
 | 
			
		||||
    def save (self, *args, **kwargs):
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.conf.urls import url
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
@ -118,7 +119,7 @@ class ThreadRoute(Route):
 | 
			
		||||
        thread_model = ContentType.objects.get_for_model(thread_model)
 | 
			
		||||
        return model.objects.filter(
 | 
			
		||||
            thread_type = thread_model,
 | 
			
		||||
            thread_pk = int(pk)
 | 
			
		||||
            thread_id = int(pk)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -143,15 +144,16 @@ class SearchRoute(Route):
 | 
			
		||||
    name = 'search'
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset(cl, website, model, request, q, **kwargs):
 | 
			
		||||
        qs = model.objects
 | 
			
		||||
    def get_queryset(cl, website, model, request, **kwargs):
 | 
			
		||||
        q = request.GET.get('q') or ''
 | 
			
		||||
        qs = None
 | 
			
		||||
 | 
			
		||||
        for search_field in model.search_fields or []:
 | 
			
		||||
            r = model.objects.filter(**{ search_field + '__icontains': q })
 | 
			
		||||
            r = models.Q(**{ search_field + '__icontains': q })
 | 
			
		||||
            if qs: qs = qs | r
 | 
			
		||||
            else: qs = r
 | 
			
		||||
 | 
			
		||||
        qs.distinct()
 | 
			
		||||
        return qs
 | 
			
		||||
        return model.objects.filter(qs).distinct()
 | 
			
		||||
 | 
			
		||||
## TODO: by tag
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,9 +24,10 @@ body {
 | 
			
		||||
    vertical-align: top;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
main .section {
 | 
			
		||||
    width: calc(50% - 2em);
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
/*    width: calc(50% - 2em);
 | 
			
		||||
    display: inline-block; */
 | 
			
		||||
    padding: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
{% block pre_title %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,9 +0,0 @@
 | 
			
		||||
 | 
			
		||||
<{{ tag }} class="section {{ classes }}"
 | 
			
		||||
    {% for key, value in attrs.items %}{{ key }} = "{{ value|addslashes }}"
 | 
			
		||||
    {% endfor %} >
 | 
			
		||||
{% block content %}
 | 
			
		||||
{{ content|safe }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
</{{ tag }}>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								cms/templates/aircox/cms/content_object.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								cms/templates/aircox/cms/content_object.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
 | 
			
		||||
<{{ tag }} class="{{ classes }}"
 | 
			
		||||
    {% for k, v in attrs.items %}{{ k }} = "{{ v|addslashes }}" {% endfor %} >
 | 
			
		||||
    {% block content %}
 | 
			
		||||
    {{ content|safe }}
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
</{{ tag }}>
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
{% extends embed|yesno:"aircox/cms/base_content.html,aircox/cms/base_site.html" %}
 | 
			
		||||
{% extends "aircox/cms/website.html" %}
 | 
			
		||||
{% load aircox_cms %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
@ -29,8 +29,6 @@
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% for section in sections %}
 | 
			
		||||
{{ section|safe }}
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{{ content }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
{% extends embed|yesno:"aircox/cms/base_content.html,aircox/cms/base_site.html" %}
 | 
			
		||||
{% extends "aircox/cms/website.html" %}
 | 
			
		||||
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load thumbnail %}
 | 
			
		||||
@ -23,7 +23,7 @@
 | 
			
		||||
        </time>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {% if 'image' in view.fields %}
 | 
			
		||||
        {% if 'image' in view.fields and post.image %}
 | 
			
		||||
        <img src="{% thumbnail post.image view.icon_size crop %}" class="post_image">
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
{% extends "aircox/cms/base_section.html" %}
 | 
			
		||||
{% extends "aircox/cms/content_object.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% if title %}
 | 
			
		||||
@ -30,5 +30,5 @@
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
</footer>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
{% load thumbnail %}
 | 
			
		||||
 | 
			
		||||
{% block section_content %}
 | 
			
		||||
% block section_content %}
 | 
			
		||||
<ul style="padding:0; margin:0">
 | 
			
		||||
    {% for item in object_list %}
 | 
			
		||||
    <li class="{{item.css}}">
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
{% if not embed %}
 | 
			
		||||
{% load staticfiles %}
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
@ -32,6 +33,7 @@
 | 
			
		||||
                {% endif %}
 | 
			
		||||
 | 
			
		||||
                <main>
 | 
			
		||||
{% endif %}
 | 
			
		||||
                    {% block pre_title %}
 | 
			
		||||
                    {% endblock %}
 | 
			
		||||
                    <h1>
 | 
			
		||||
@ -45,6 +47,7 @@
 | 
			
		||||
                        {% block content %}
 | 
			
		||||
                        {% endblock %}
 | 
			
		||||
                    </div>
 | 
			
		||||
{% if not embed %}
 | 
			
		||||
                </main>
 | 
			
		||||
 | 
			
		||||
                {% if menus.right %}
 | 
			
		||||
@ -68,4 +71,5 @@
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								cms/utils.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								cms/utils.py
									
									
									
									
									
								
							@ -1,21 +0,0 @@
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.core.urlresolvers import reverse
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_url(website, route, model, kwargs):
 | 
			
		||||
    name = website.name_of_model(model)
 | 
			
		||||
    if not name:
 | 
			
		||||
        return
 | 
			
		||||
    name = route.get_view_name(name)
 | 
			
		||||
    return reverse(name, kwargs = kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def filter_thread(qs, object):
 | 
			
		||||
    model_type = ContentType.objects.get_for_model(object.__class__)
 | 
			
		||||
    return qs.filter(
 | 
			
		||||
        thread_pk = object.pk,
 | 
			
		||||
        thread_type__pk = model_type.pk
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										311
									
								
								cms/views.py
									
									
									
									
									
								
							
							
						
						
									
										311
									
								
								cms/views.py
									
									
									
									
									
								
							@ -1,17 +1,8 @@
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
from django.templatetags.static import static
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.template.loader import render_to_string
 | 
			
		||||
from django.views.generic import ListView, DetailView
 | 
			
		||||
from django.views.generic.base import View, TemplateResponseMixin
 | 
			
		||||
from django.core.paginator import Paginator
 | 
			
		||||
from django.core import serializers
 | 
			
		||||
from django.views.generic.base import View
 | 
			
		||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
			
		||||
from django.utils.html import escape
 | 
			
		||||
 | 
			
		||||
import aircox.cms.routes as routes
 | 
			
		||||
import aircox.cms.utils as utils
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostBaseView:
 | 
			
		||||
@ -46,43 +37,26 @@ class PostBaseView:
 | 
			
		||||
 | 
			
		||||
class PostListView(PostBaseView, ListView):
 | 
			
		||||
    """
 | 
			
		||||
    List view for posts and children
 | 
			
		||||
    List view for posts and children.
 | 
			
		||||
 | 
			
		||||
    Request.GET params:
 | 
			
		||||
    * embed: view is embedded, render only the list
 | 
			
		||||
    * exclude: exclude item of the given id
 | 
			
		||||
    * order: 'desc' or 'asc'
 | 
			
		||||
    * fields: fields to render
 | 
			
		||||
    * page: page number
 | 
			
		||||
    """
 | 
			
		||||
    class Query:
 | 
			
		||||
        """
 | 
			
		||||
        Request availables parameters
 | 
			
		||||
        """
 | 
			
		||||
        embed = False   # view is embedded (only the list is shown)
 | 
			
		||||
        exclude = None  # exclude item of this id
 | 
			
		||||
        order = 'desc'  # order of the list when query
 | 
			
		||||
        fields = None   # fields to show
 | 
			
		||||
        page = 1        # page number
 | 
			
		||||
        q = None        # query search
 | 
			
		||||
 | 
			
		||||
        def __init__(self, query):
 | 
			
		||||
            if query:
 | 
			
		||||
                self.update(query)
 | 
			
		||||
 | 
			
		||||
        def update(self, query):
 | 
			
		||||
            my_class = self.__class__
 | 
			
		||||
            if type(query) is my_class:
 | 
			
		||||
                self.__dict__.update(query.__dict__)
 | 
			
		||||
                return
 | 
			
		||||
            self.__dict__.update(query)
 | 
			
		||||
 | 
			
		||||
    template_name = 'aircox/cms/list.html'
 | 
			
		||||
    allow_empty = True
 | 
			
		||||
    paginate_by = 50
 | 
			
		||||
    model = None
 | 
			
		||||
 | 
			
		||||
    route = None
 | 
			
		||||
    query = None
 | 
			
		||||
    fields = [ 'date', 'time', 'image', 'title', 'content' ]
 | 
			
		||||
    icon_size = '64x64'
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.query = PostListView.Query(self.query)
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        self.route = self.kwargs.get('route') or self.route
 | 
			
		||||
@ -94,23 +68,22 @@ class PostListView(PostBaseView, ListView):
 | 
			
		||||
                                         **self.kwargs)
 | 
			
		||||
        else:
 | 
			
		||||
            qs = self.queryset or self.model.objects.all()
 | 
			
		||||
        query = self.query
 | 
			
		||||
 | 
			
		||||
        query.update(self.request.GET)
 | 
			
		||||
        if query.exclude:
 | 
			
		||||
            qs = qs.exclude(id = int(exclude))
 | 
			
		||||
        query = self.request.GET
 | 
			
		||||
        if query.get('exclude'):
 | 
			
		||||
            qs = qs.exclude(id = int(query['exclude']))
 | 
			
		||||
 | 
			
		||||
        if query.embed:
 | 
			
		||||
        if query.get('embed'):
 | 
			
		||||
            self.embed = True
 | 
			
		||||
 | 
			
		||||
        if query.order == 'asc':
 | 
			
		||||
        if query.get('order') == 'asc':
 | 
			
		||||
            qs.order_by('date', 'id')
 | 
			
		||||
        else:
 | 
			
		||||
            qs.order_by('-date', '-id')
 | 
			
		||||
 | 
			
		||||
        if query.fields:
 | 
			
		||||
        if query.get('fields'):
 | 
			
		||||
            self.fields = [
 | 
			
		||||
                field for field in query.fields
 | 
			
		||||
                field for field in query.get('fields')
 | 
			
		||||
                if field in self.__class__.fields
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
@ -134,14 +107,16 @@ class PostListView(PostBaseView, ListView):
 | 
			
		||||
 | 
			
		||||
    def get_url(self):
 | 
			
		||||
        if self.route:
 | 
			
		||||
            return utils.get_urls(self.website, self.route,
 | 
			
		||||
                                  self.model, self.kwargs)
 | 
			
		||||
            return self.model(self.route, self.kwargs)
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostDetailView(DetailView, PostBaseView):
 | 
			
		||||
    """
 | 
			
		||||
    Detail view for posts and children
 | 
			
		||||
 | 
			
		||||
    Request.GET params:
 | 
			
		||||
    * embed: view is embedded, only render the content
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox/cms/detail.html'
 | 
			
		||||
 | 
			
		||||
@ -149,12 +124,11 @@ class PostDetailView(DetailView, PostBaseView):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sections = None, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.sections = sections or []
 | 
			
		||||
        self.sections = Sections(sections = sections)
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        if self.request.GET.get('embed'):
 | 
			
		||||
            self.embed = True
 | 
			
		||||
 | 
			
		||||
        if self.model:
 | 
			
		||||
            return super().get_queryset().filter(published = True)
 | 
			
		||||
        return []
 | 
			
		||||
@ -169,237 +143,52 @@ class PostDetailView(DetailView, PostBaseView):
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update(self.get_base_context())
 | 
			
		||||
        context.update({
 | 
			
		||||
            'sections': [
 | 
			
		||||
                section.get(self.request, website = self.website, **kwargs)
 | 
			
		||||
                    for section in self.sections
 | 
			
		||||
            ]
 | 
			
		||||
        })
 | 
			
		||||
        context['content'] = self.sections.get(request, object = self.object,
 | 
			
		||||
                                               **kwargs)
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Menu(View):
 | 
			
		||||
    template_name = 'aircox/cms/menu.html'
 | 
			
		||||
 | 
			
		||||
    name = ''
 | 
			
		||||
    tag = 'nav'
 | 
			
		||||
    enabled = True
 | 
			
		||||
class Sections(View):
 | 
			
		||||
    template_name = 'aircox/cms/content_object.html'
 | 
			
		||||
    tag = 'div'
 | 
			
		||||
    classes = ''
 | 
			
		||||
    position = ''   # top, left, bottom, right, header, footer, page_top, page_bottom
 | 
			
		||||
    attrs = ''
 | 
			
		||||
    sections = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
    def __init__ (self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.name = self.name or ('menu_' + self.position)
 | 
			
		||||
        self.classes += ' sections'
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
    def get_context_data(self, request, object = None, **kwargs):
 | 
			
		||||
        return {
 | 
			
		||||
            'name': self.name,
 | 
			
		||||
            'tag': self.tag,
 | 
			
		||||
            'classes': self.classes,
 | 
			
		||||
            'position': self.position,
 | 
			
		||||
            'sections': [
 | 
			
		||||
                section.get(self.request, website = self.website,
 | 
			
		||||
                            object = None, **kwargs)
 | 
			
		||||
                    for section in self.sections
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def get(self, request, website, **kwargs):
 | 
			
		||||
        self.request = request
 | 
			
		||||
        self.website = website
 | 
			
		||||
        context = self.get_context_data(**kwargs)
 | 
			
		||||
        return render_to_string(self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseSection(View):
 | 
			
		||||
    """
 | 
			
		||||
    Base class for sections. Sections are view that can be used in detail view
 | 
			
		||||
    in order to have extra content about a post, or in menus.
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox/cms/base_section.html'
 | 
			
		||||
    kwargs = None   # kwargs argument passed to get
 | 
			
		||||
    tag = 'div'     # container tags
 | 
			
		||||
    classes = ''    # container classes
 | 
			
		||||
    attrs = ''      # container extra attributes
 | 
			
		||||
    content = ''    # content
 | 
			
		||||
    visible = True  # if false renders an empty string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self):
 | 
			
		||||
        return {
 | 
			
		||||
            'view': self,
 | 
			
		||||
            'tag': self.tag,
 | 
			
		||||
            'classes': self.classes,
 | 
			
		||||
            'attrs': self.attrs,
 | 
			
		||||
            'visible': self.visible,
 | 
			
		||||
            'content': self.content,
 | 
			
		||||
            'content': ''.join([
 | 
			
		||||
                section.get(request, object = object, **kwargs)
 | 
			
		||||
                    for section in self.sections or []
 | 
			
		||||
            ])
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def get(self, request, website, **kwargs):
 | 
			
		||||
        self.request = request
 | 
			
		||||
        self.website = website
 | 
			
		||||
        self.kwargs = kwargs
 | 
			
		||||
 | 
			
		||||
        context = self.get_context_data()
 | 
			
		||||
        # get_context_data may call extra function that can change visibility
 | 
			
		||||
        if self.visible:
 | 
			
		||||
            return render_to_string(self.template_name, context)
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Section(BaseSection):
 | 
			
		||||
    """
 | 
			
		||||
    A Section that can be related to an object.
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'aircox/cms/section.html'
 | 
			
		||||
    object = None
 | 
			
		||||
    object_required = False
 | 
			
		||||
    title = ''
 | 
			
		||||
    header = ''
 | 
			
		||||
    footer = ''
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self):
 | 
			
		||||
        context = super().get_context_data()
 | 
			
		||||
        context.update({
 | 
			
		||||
            'title': self.title,
 | 
			
		||||
            'header': self.header,
 | 
			
		||||
            'footer': self.footer,
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    def get(self, request, object = None, **kwargs):
 | 
			
		||||
        self.object = object or self.object
 | 
			
		||||
        if self.object_required and not self.object:
 | 
			
		||||
            raise ValueError('object is required by this Section but not given')
 | 
			
		||||
        return super().get(request, **kwargs)
 | 
			
		||||
        self.request = request
 | 
			
		||||
        context = self.get_context_data(request, object, **kwargs)
 | 
			
		||||
        return render_to_string(self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Sections:
 | 
			
		||||
    class Image(BaseSection):
 | 
			
		||||
        """
 | 
			
		||||
        Render an image with the given relative url.
 | 
			
		||||
        """
 | 
			
		||||
        url = None
 | 
			
		||||
class Menu(Sections):
 | 
			
		||||
    name = ''
 | 
			
		||||
    tag = 'nav'
 | 
			
		||||
    enabled = True
 | 
			
		||||
    position = ''   # top, left, bottom, right, header, footer, page_top, page_bottom
 | 
			
		||||
 | 
			
		||||
        @property
 | 
			
		||||
        def content(self):
 | 
			
		||||
            return '<img src="{}">'.format(
 | 
			
		||||
                        static(self.url),
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
    class PostContent(Section):
 | 
			
		||||
        """
 | 
			
		||||
        Render the content of the Post (format the text a bit and escape HTML
 | 
			
		||||
        tags).
 | 
			
		||||
        """
 | 
			
		||||
        @property
 | 
			
		||||
        def content(self):
 | 
			
		||||
            content = escape(self.object.content)
 | 
			
		||||
            content = re.sub(r'(^|\n\n)((\n?[^\n])+)', r'<p>\2</p>', content)
 | 
			
		||||
            content = re.sub(r'\n', r'<br>', content)
 | 
			
		||||
            return content
 | 
			
		||||
 | 
			
		||||
    class PostImage(Section):
 | 
			
		||||
        """
 | 
			
		||||
        Render the image of the Post
 | 
			
		||||
        """
 | 
			
		||||
        @property
 | 
			
		||||
        def content(self):
 | 
			
		||||
            if not self.object.image:
 | 
			
		||||
                return ''
 | 
			
		||||
            return '<img src="{}" class="post_image">'.format(
 | 
			
		||||
                        self.object.image.url
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
    class List(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
 | 
			
		||||
            url = None
 | 
			
		||||
            css = None
 | 
			
		||||
 | 
			
		||||
            def __init__(self, icon, title = None, text = None, url = None, css = None):
 | 
			
		||||
                self.icon = icon
 | 
			
		||||
                self.title = title
 | 
			
		||||
                self.text = text
 | 
			
		||||
                self.css = css
 | 
			
		||||
 | 
			
		||||
        hide_empty = False      # hides the section if the list is empty
 | 
			
		||||
        use_icons = True        # print icons
 | 
			
		||||
        paginate_by = 0         # number of items
 | 
			
		||||
        icon_size = '32x32'     # icons size
 | 
			
		||||
        template_name = 'aircox/cms/section_list.html'
 | 
			
		||||
 | 
			
		||||
        def get_object_list(self):
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        def get_context_data(self, **kwargs):
 | 
			
		||||
            object_list = self.get_object_list()
 | 
			
		||||
            self.visibility = True
 | 
			
		||||
            if not object_list and self.hide_empty:
 | 
			
		||||
                self.visibility = False
 | 
			
		||||
 | 
			
		||||
            context = super().get_context_data(**kwargs)
 | 
			
		||||
            context.update({
 | 
			
		||||
                'classes': context.get('classes') + ' section_list',
 | 
			
		||||
                'icon_size': self.icon_size,
 | 
			
		||||
                'object_list': object_list,
 | 
			
		||||
                'paginate_by': self.paginate_by,
 | 
			
		||||
            })
 | 
			
		||||
            return context
 | 
			
		||||
 | 
			
		||||
    class Urls(List):
 | 
			
		||||
        """
 | 
			
		||||
        Render a list of urls of targets that are Posts
 | 
			
		||||
        """
 | 
			
		||||
        classes = 'section_urls'
 | 
			
		||||
        targets = None
 | 
			
		||||
 | 
			
		||||
        def get_object_list(self):
 | 
			
		||||
            return [
 | 
			
		||||
                List.Item(
 | 
			
		||||
                    target.image or None,
 | 
			
		||||
                    target.title,
 | 
			
		||||
                    url = target.detail_url(),
 | 
			
		||||
                )
 | 
			
		||||
                for target in self.targets
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
    class Posts(PostBaseView, Section):
 | 
			
		||||
        """
 | 
			
		||||
        Render a list using PostListView's template.
 | 
			
		||||
        """
 | 
			
		||||
        embed = True
 | 
			
		||||
        paginate_by = 5
 | 
			
		||||
        icon_size = '64x64'
 | 
			
		||||
        fields = [ 'date', 'time', 'image', 'title', 'content' ]
 | 
			
		||||
 | 
			
		||||
        def get_url(self):
 | 
			
		||||
            return ''
 | 
			
		||||
 | 
			
		||||
        def get_object_list(self):
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        def render_list(self):
 | 
			
		||||
            self.embed = True
 | 
			
		||||
            context = self.get_base_context(**self.kwargs)
 | 
			
		||||
            context.update({
 | 
			
		||||
                'object_list': self.get_object_list(),
 | 
			
		||||
                'embed': True,
 | 
			
		||||
                'paginate_by': self.paginate_by,
 | 
			
		||||
            })
 | 
			
		||||
            return render_to_string(PostListView.template_name, context)
 | 
			
		||||
 | 
			
		||||
        def get_context_data(self, **kwargs):
 | 
			
		||||
            context = super().get_context_data(**kwargs)
 | 
			
		||||
            context['content'] = self.render_list()
 | 
			
		||||
            return context
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.classes += ' menu menu_{}'.format(self.name or self.position)
 | 
			
		||||
        if not self.attrs:
 | 
			
		||||
            self.attrs = {}
 | 
			
		||||
        if self.name:
 | 
			
		||||
            self.attrs['name'] = self.name
 | 
			
		||||
            self.attrs['id'] = self.name
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ class Website:
 | 
			
		||||
        view = view.as_view(
 | 
			
		||||
            website = self,
 | 
			
		||||
            model = model,
 | 
			
		||||
            **view_kwargs,
 | 
			
		||||
            **view_kwargs
 | 
			
		||||
        )
 | 
			
		||||
        self.urls.append(routes.DetailRoute.as_url(name, view))
 | 
			
		||||
        self.registry[name] = model
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user