forked from rc/aircox
		
	rename
This commit is contained in:
		@ -1,3 +0,0 @@
 | 
			
		||||
from django.contrib import admin
 | 
			
		||||
 | 
			
		||||
# Register your models here.
 | 
			
		||||
							
								
								
									
										187
									
								
								cms/models.py
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								cms/models.py
									
									
									
									
									
								
							@ -1,187 +0,0 @@
 | 
			
		||||
from django.db import models
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.contrib.contenttypes.fields import GenericForeignKey
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.text import slugify
 | 
			
		||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
			
		||||
from django.core.urlresolvers import reverse
 | 
			
		||||
 | 
			
		||||
from django.db.models.signals import post_init, post_save, post_delete
 | 
			
		||||
from django.dispatch import receiver
 | 
			
		||||
 | 
			
		||||
from taggit.managers import TaggableManager
 | 
			
		||||
 | 
			
		||||
class Thread (models.Model):
 | 
			
		||||
    """
 | 
			
		||||
    Object assigned to any Post and children that can be used to have parent and
 | 
			
		||||
    children relationship between posts of different kind.
 | 
			
		||||
 | 
			
		||||
    We use this system instead of having directly a GenericForeignKey into the
 | 
			
		||||
    Post because it avoids having to define the relationship with two models for
 | 
			
		||||
    routing (one for the parent and one for the children).
 | 
			
		||||
    """
 | 
			
		||||
    post_type = models.ForeignKey(ContentType)
 | 
			
		||||
    post_id = models.PositiveIntegerField()
 | 
			
		||||
    post = GenericForeignKey('post_type', 'post_id')
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def __get_query_set (cl, function, model, post, kwargs):
 | 
			
		||||
        if post:
 | 
			
		||||
            model = type(post)
 | 
			
		||||
            kwargs['post_id'] = post.id
 | 
			
		||||
 | 
			
		||||
        kwargs['post_type'] = ContentType.objects.get_for_model(model)
 | 
			
		||||
        return getattr(cl.objects, function)(**kwargs)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get (cl, model = None, post = None, **kwargs):
 | 
			
		||||
        return cl.__get_query_set('get', model, post, kwargs)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def filter (cl, model = None, post = None, **kwargs):
 | 
			
		||||
        return self.__get_query_set('filter', model, post, kwargs)
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def exclude (cl, model = None, post = None, **kwargs):
 | 
			
		||||
        return self.__get_query_set('exclude', model, post, kwargs)
 | 
			
		||||
 | 
			
		||||
    def save (self, *args, **kwargs):
 | 
			
		||||
        self.post = self.__initial_post
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def __str__ (self):
 | 
			
		||||
        return self.post_type.name + ': ' + str(self.post)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Post (models.Model):
 | 
			
		||||
    thread = models.ForeignKey(
 | 
			
		||||
        Thread,
 | 
			
		||||
        on_delete=models.SET_NULL,
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
        help_text = _('the publication is posted on this thread'),
 | 
			
		||||
    )
 | 
			
		||||
    author = models.ForeignKey(
 | 
			
		||||
        User,
 | 
			
		||||
        verbose_name = _('author'),
 | 
			
		||||
        blank = True, null = True,
 | 
			
		||||
    )
 | 
			
		||||
    date = models.DateTimeField(
 | 
			
		||||
        _('date'),
 | 
			
		||||
        default = timezone.datetime.now
 | 
			
		||||
    )
 | 
			
		||||
    published = models.BooleanField(
 | 
			
		||||
        verbose_name = _('public'),
 | 
			
		||||
        default = True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    title = models.CharField (
 | 
			
		||||
        _('title'),
 | 
			
		||||
        max_length = 128,
 | 
			
		||||
    )
 | 
			
		||||
    content = models.TextField (
 | 
			
		||||
        _('description'),
 | 
			
		||||
        blank = True, null = True
 | 
			
		||||
    )
 | 
			
		||||
    image = models.ImageField(
 | 
			
		||||
        blank = True, null = True
 | 
			
		||||
    )
 | 
			
		||||
    tags = TaggableManager(
 | 
			
		||||
        _('tags'),
 | 
			
		||||
        blank = True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def detail_url (self):
 | 
			
		||||
        return reverse(self._meta.verbose_name_plural.lower() + '_detail',
 | 
			
		||||
                       kwargs = { 'pk': self.pk,
 | 
			
		||||
                                  'slug': slugify(self.title) })
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Article (Post):
 | 
			
		||||
    static_page = models.BooleanField(
 | 
			
		||||
        _('static page'),
 | 
			
		||||
        default = False,
 | 
			
		||||
    )
 | 
			
		||||
    focus = models.BooleanField(
 | 
			
		||||
        _('article is focus'),
 | 
			
		||||
        default = False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _('Article')
 | 
			
		||||
        verbose_name_plural = _('Articles')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RelatedPostBase (models.base.ModelBase):
 | 
			
		||||
    """
 | 
			
		||||
    Metaclass for RelatedPost children.
 | 
			
		||||
    """
 | 
			
		||||
    def __new__ (cls, name, bases, attrs):
 | 
			
		||||
        rel = attrs.get('Relation')
 | 
			
		||||
        rel = (rel and rel.__dict__) or {}
 | 
			
		||||
 | 
			
		||||
        related_model = rel.get('related_model')
 | 
			
		||||
        if related_model:
 | 
			
		||||
            attrs['related'] = models.ForeignKey(related_model)
 | 
			
		||||
 | 
			
		||||
        if not '__str__' in attrs:
 | 
			
		||||
            attrs['__str__'] = lambda self: str(self.related)
 | 
			
		||||
 | 
			
		||||
        return super().__new__(cls, name, bases, attrs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
			
		||||
    related = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    class Relation:
 | 
			
		||||
        related_model = None
 | 
			
		||||
        mapping = None          # dict of related mapping values
 | 
			
		||||
        bind_mapping = False    # update fields of related data on save
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def get_attribute (self, attr):
 | 
			
		||||
        attr = self.Relation.mappings.get(attr)
 | 
			
		||||
        return self.related.__dict__[attr] if attr else None
 | 
			
		||||
 | 
			
		||||
    def save (self, *args, **kwargs):
 | 
			
		||||
        if not self.title and self.related:
 | 
			
		||||
            self.title = self.get_attribute('title')
 | 
			
		||||
 | 
			
		||||
        if self.Relation.bind_mapping:
 | 
			
		||||
            self.related.__dict__.update({
 | 
			
		||||
                rel_attr: self.__dict__[attr]
 | 
			
		||||
                for attr, rel_attr in self.Relation.mapping
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
            self.related.save()
 | 
			
		||||
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@receiver(post_init)
 | 
			
		||||
def on_thread_init (sender, instance, **kwargs):
 | 
			
		||||
    if not issubclass(Thread, sender):
 | 
			
		||||
        return
 | 
			
		||||
    instance.__initial_post = instance.post
 | 
			
		||||
 | 
			
		||||
@receiver(post_save)
 | 
			
		||||
def on_post_save (sender, instance, created, *args, **kwargs):
 | 
			
		||||
    if not issubclass(sender, Post) or not created:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    thread = Thread(post = instance)
 | 
			
		||||
    thread.save()
 | 
			
		||||
 | 
			
		||||
@receiver(post_delete)
 | 
			
		||||
def on_post_delete (sender, instance, using, *args, **kwargs):
 | 
			
		||||
    try:
 | 
			
		||||
        Thread.get(sender, post = instance).delete()
 | 
			
		||||
    except:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										154
									
								
								cms/routes.py
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								cms/routes.py
									
									
									
									
									
								
							@ -1,154 +0,0 @@
 | 
			
		||||
from django.conf.urls import url
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
			
		||||
 | 
			
		||||
from website.models import *
 | 
			
		||||
from website.views import *
 | 
			
		||||
 | 
			
		||||
class Router:
 | 
			
		||||
    registry = []
 | 
			
		||||
 | 
			
		||||
    def register (self, route):
 | 
			
		||||
        if not route in self.registry:
 | 
			
		||||
            self.registry.append(route)
 | 
			
		||||
 | 
			
		||||
    def register_set (self, view_set):
 | 
			
		||||
        for url in view_set.urls:
 | 
			
		||||
            self.register(url)
 | 
			
		||||
 | 
			
		||||
    def unregister (self, route):
 | 
			
		||||
        self.registry.remove(route)
 | 
			
		||||
 | 
			
		||||
    def get_urlpatterns (self):
 | 
			
		||||
        return [ url for url in self.registry ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Route:
 | 
			
		||||
    """
 | 
			
		||||
    Base class for routing. Given a model, we generate url specific for each
 | 
			
		||||
    route type. The generated url takes this form:
 | 
			
		||||
        base_name + '/' + route_name + '/' + '/'.join(route_url_args)
 | 
			
		||||
 | 
			
		||||
    Where base_name by default is the given model's verbose_name (uses plural if
 | 
			
		||||
    Route is for a list).
 | 
			
		||||
 | 
			
		||||
    The given view is considered as a django class view, and has view_
 | 
			
		||||
    """
 | 
			
		||||
    name = None         # route name
 | 
			
		||||
    url_args = []       # arguments passed from the url [ (name : regex),... ]
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset (cl, model, request, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Called by the view to get the queryset when it is needed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_object (cl, model, request, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Called by the view to get the object when it is needed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_title (cl, model, request, **kwargs):
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def as_url (cl, model, view, view_kwargs = None):
 | 
			
		||||
        base_name = model._meta.verbose_name_plural.lower()
 | 
			
		||||
 | 
			
		||||
        pattern = '^{}/{}'.format(base_name, cl.name)
 | 
			
		||||
        if cl.url_args:
 | 
			
		||||
            url_args = '/'.join([
 | 
			
		||||
                '(?P<{}>{}){}'.format(
 | 
			
		||||
                    arg, expr,
 | 
			
		||||
                    (optional and optional[0] and '?') or ''
 | 
			
		||||
                )
 | 
			
		||||
                for arg, expr, *optional in cl.url_args
 | 
			
		||||
            ])
 | 
			
		||||
            pattern += '/' + url_args
 | 
			
		||||
        pattern += '/?$'
 | 
			
		||||
 | 
			
		||||
        kwargs = {
 | 
			
		||||
            'route': cl,
 | 
			
		||||
        }
 | 
			
		||||
        if view_kwargs:
 | 
			
		||||
            kwargs.update(view_kwargs)
 | 
			
		||||
 | 
			
		||||
        return url(pattern, view, kwargs = kwargs,
 | 
			
		||||
                   name = base_name + '_' + cl.name)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DetailRoute (Route):
 | 
			
		||||
    name = 'detail'
 | 
			
		||||
    url_args = [
 | 
			
		||||
        ('pk', '[0-9]+'),
 | 
			
		||||
        ('slug', '(\w|-|_)+', True),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_object (cl, model, request, pk, **kwargs):
 | 
			
		||||
        return model.objects.get(pk = int(pk))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AllRoute (Route):
 | 
			
		||||
    name = 'all'
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset (cl, model, request, **kwargs):
 | 
			
		||||
        return model.objects.all()
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_title (cl, model, request, **kwargs):
 | 
			
		||||
        return _('All %(model)s') % {
 | 
			
		||||
            'model': model._meta.verbose_name_plural
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ThreadRoute (Route):
 | 
			
		||||
    name = 'thread'
 | 
			
		||||
    url_args = [
 | 
			
		||||
        ('pk', '[0-9]+'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset (cl, model, request, pk, **kwargs):
 | 
			
		||||
        return model.objects.filter(thread__pk = int(pk))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DateRoute (Route):
 | 
			
		||||
    name = 'date'
 | 
			
		||||
    url_args = [
 | 
			
		||||
        ('year', '[0-9]{4}'),
 | 
			
		||||
        ('month', '[0-9]{2}'),
 | 
			
		||||
        ('day', '[0-9]{1,2}'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset (cl, model, request, year, month, day, **kwargs):
 | 
			
		||||
        return model.objects.filter(
 | 
			
		||||
            date__year = int(year),
 | 
			
		||||
            date__month = int(month),
 | 
			
		||||
            date__day = int(day),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SearchRoute (Route):
 | 
			
		||||
    name = 'search'
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_queryset (cl, model, request, **kwargs):
 | 
			
		||||
        q = request.GET.get('q') or ''
 | 
			
		||||
        qs = model.objects
 | 
			
		||||
        for search_field in model.search_fields or []:
 | 
			
		||||
            r = model.objects.filter(**{ search_field + '__icontains': q })
 | 
			
		||||
            if qs: qs = qs | r
 | 
			
		||||
            else: qs = r
 | 
			
		||||
 | 
			
		||||
        qs.distinct()
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
{% block pre_title %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block title %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,49 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title>{{ website.name }} {% if title %}- {{ title }} {% endif %}</title>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        {% if menus.top %}
 | 
			
		||||
            {{ menus.top|safe }}
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {% block header %}
 | 
			
		||||
            {% if menus.header %}
 | 
			
		||||
            <header>
 | 
			
		||||
                {{ menus.header|safe }}
 | 
			
		||||
            </header>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
 | 
			
		||||
        <div class="page">
 | 
			
		||||
            {% if menus.left %}
 | 
			
		||||
                {{ menus.left|safe }}
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 | 
			
		||||
            <main>
 | 
			
		||||
                {% block pre_title %}
 | 
			
		||||
                {% endblock %}
 | 
			
		||||
                <h1>
 | 
			
		||||
                    {% block title %}
 | 
			
		||||
                    {{ title }}
 | 
			
		||||
                    {% endblock %}
 | 
			
		||||
                </h1>
 | 
			
		||||
                {% block post_title %}
 | 
			
		||||
                {% endblock %}
 | 
			
		||||
                <div class="content">
 | 
			
		||||
                    {% block content %}
 | 
			
		||||
                    {% endblock %}
 | 
			
		||||
                </div>
 | 
			
		||||
            </main>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {% block footer %}
 | 
			
		||||
            {% if menus.footer %}
 | 
			
		||||
            <footer>
 | 
			
		||||
                {{ menus.footer|safe }}
 | 
			
		||||
            </footer>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
@ -1,19 +0,0 @@
 | 
			
		||||
{% extends embed|yesno:"cms/base_content.html,cms/base_site.html" %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
{{ object.title }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block pre_title %}
 | 
			
		||||
<time datetime="{{ object.date }}">
 | 
			
		||||
    {{ object.date|date:'l d F Y' }},
 | 
			
		||||
    {{ object.date|time:'H\hi' }}
 | 
			
		||||
</time>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% for section in sections %}
 | 
			
		||||
{{ section|safe }}
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
{# Used for embedded content #}
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
{% extends embed|yesno:"cms/base_content.html,cms/base_site.html" %}
 | 
			
		||||
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load thumbnail %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="post_list {{ classes }}">
 | 
			
		||||
{% for post in object_list %}
 | 
			
		||||
    <a class="post_item"
 | 
			
		||||
       href="{{ post.detail_url }}">
 | 
			
		||||
        {% if 'date' in view.fields or 'time' in list.fields %}
 | 
			
		||||
        <time datetime="{{ post.date }}" class="post_datetime">
 | 
			
		||||
            {% if 'date' in view.fields %}
 | 
			
		||||
            <span class="post_date">
 | 
			
		||||
                {{ post.date|date:'D. d F' }},
 | 
			
		||||
            </span>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            {% if 'time' in view.fields %}
 | 
			
		||||
            <span class="post_time">
 | 
			
		||||
                {{ post.date|date:'H:i' }},
 | 
			
		||||
            </span>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        </time>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {% if 'image' in view.fields %}
 | 
			
		||||
        <img src="{% thumbnail post.image "64x64" crop %}" class="post_image">
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {% if 'title' in view.fields %}
 | 
			
		||||
        <h4 class="post_title">{{ post.title }}</h4>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {% if 'content' in view.fields %}
 | 
			
		||||
        <div class="post_content">
 | 
			
		||||
        {{ post.content|safe|striptags|truncatechars:"64" }}
 | 
			
		||||
        </div>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </a>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
 | 
			
		||||
<nav class="menu menu_{{ position }} {{ classes }}" {% if name %}
 | 
			
		||||
        name="menu_{{ name }}"
 | 
			
		||||
        id="menu_{{ name }}"
 | 
			
		||||
    {% endif %}>
 | 
			
		||||
    {% for section in sections %}
 | 
			
		||||
    {{ section|safe }}
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
</nav>
 | 
			
		||||
 | 
			
		||||
@ -1,33 +0,0 @@
 | 
			
		||||
<div class="section {{ classes }}">
 | 
			
		||||
    {% if title %}
 | 
			
		||||
    <h1>
 | 
			
		||||
        {% block section_title %}
 | 
			
		||||
        {{ title }}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </h1>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if header %}
 | 
			
		||||
    <header class="section_header">
 | 
			
		||||
        {% block section_header %}
 | 
			
		||||
        {{ header }}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </header>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    <div class="section_content">
 | 
			
		||||
        {% block section_content %}
 | 
			
		||||
        {{ content|safe }}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {% if bottom %}
 | 
			
		||||
    <div class="section_bottom">
 | 
			
		||||
        {% block section_bottom %}
 | 
			
		||||
        {{ bottom }}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
{% extends "cms/section.html" %}
 | 
			
		||||
 | 
			
		||||
{% load thumbnail %}
 | 
			
		||||
 | 
			
		||||
{% block section_content %}
 | 
			
		||||
<ul style="padding:0; margin:0">
 | 
			
		||||
    {% for item in object_list %}
 | 
			
		||||
    <li>
 | 
			
		||||
        {% if use_icons and item.icon %}
 | 
			
		||||
        <img src="{% thumbnail item.icon icon_size crop %}" class="icon">
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
        {{ item.title }}
 | 
			
		||||
 | 
			
		||||
        {% if item.text %}
 | 
			
		||||
            <small>{{ item.text }}</small>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </li>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
</ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										322
									
								
								cms/views.py
									
									
									
									
									
								
							
							
						
						
									
										322
									
								
								cms/views.py
									
									
									
									
									
								
							@ -1,322 +0,0 @@
 | 
			
		||||
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 import serializers
 | 
			
		||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
			
		||||
 | 
			
		||||
import cms.routes as routes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostBaseView:
 | 
			
		||||
    website = None  # corresponding website
 | 
			
		||||
    title = ''      # title of the page
 | 
			
		||||
    embed = False   # page is embed (if True, only post content is printed
 | 
			
		||||
    classes = ''    # extra classes for the content
 | 
			
		||||
 | 
			
		||||
    def get_base_context (self):
 | 
			
		||||
        """
 | 
			
		||||
        Return a context with all attributes of this classe plus 'view' set
 | 
			
		||||
        to self.
 | 
			
		||||
        """
 | 
			
		||||
        context = {
 | 
			
		||||
            k: getattr(self, k)
 | 
			
		||||
            for k, v in PostBaseView.__dict__.items()
 | 
			
		||||
                if not k.startswith('__')
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if not self.embed:
 | 
			
		||||
            context['menus'] = {
 | 
			
		||||
                k: v.get(self.request)
 | 
			
		||||
                for k, v in {
 | 
			
		||||
                    'top': self.website.get_menu('top'),
 | 
			
		||||
                    'left': self.website.get_menu('left'),
 | 
			
		||||
                    'bottom': self.website.get_menu('bottom'),
 | 
			
		||||
                    'right': self.website.get_menu('right'),
 | 
			
		||||
                    'header': self.website.get_menu('header'),
 | 
			
		||||
                    'footer': self.website.get_menu('footer'),
 | 
			
		||||
                }.items() if v
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        context['view'] = self
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostListView (PostBaseView, ListView):
 | 
			
		||||
    """
 | 
			
		||||
    List view for posts and children
 | 
			
		||||
    """
 | 
			
		||||
    class Query:
 | 
			
		||||
        """
 | 
			
		||||
        Request availables parameters
 | 
			
		||||
        """
 | 
			
		||||
        embed = False
 | 
			
		||||
        exclude = None
 | 
			
		||||
        order = 'desc'
 | 
			
		||||
        reverse = False
 | 
			
		||||
        fields = None
 | 
			
		||||
 | 
			
		||||
        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 = 'cms/list.html'
 | 
			
		||||
    allow_empty = True
 | 
			
		||||
 | 
			
		||||
    route = None
 | 
			
		||||
    query = None
 | 
			
		||||
    fields = [ 'date', 'time', 'image', 'title', 'content' ]
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_queryset (self):
 | 
			
		||||
        qs = self.route.get_queryset(self.model, self.request, **self.kwargs)
 | 
			
		||||
        query = self.query
 | 
			
		||||
 | 
			
		||||
        query.update(self.request.GET)
 | 
			
		||||
        if query.exclude:
 | 
			
		||||
            qs = qs.exclude(id = int(exclude))
 | 
			
		||||
 | 
			
		||||
        if query.embed:
 | 
			
		||||
            self.embed = True
 | 
			
		||||
 | 
			
		||||
        if query.order == 'asc':
 | 
			
		||||
            qs.order_by('date', 'id')
 | 
			
		||||
        else:
 | 
			
		||||
            qs.order_by('-date', '-id')
 | 
			
		||||
 | 
			
		||||
        if query.fields:
 | 
			
		||||
            self.fields = [
 | 
			
		||||
                field for field in query.fields
 | 
			
		||||
                if field in self.__class__.fields
 | 
			
		||||
            ]
 | 
			
		||||
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
    def get_context_data (self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update(self.get_base_context())
 | 
			
		||||
        context.update({
 | 
			
		||||
            'title': self.get_title(),
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    def get_title (self):
 | 
			
		||||
        if self.title:
 | 
			
		||||
            return self.title
 | 
			
		||||
 | 
			
		||||
        title = self.route and self.route.get_title(self.model, self.request,
 | 
			
		||||
                                                    **self.kwargs)
 | 
			
		||||
        return title
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostDetailView (DetailView, PostBaseView):
 | 
			
		||||
    """
 | 
			
		||||
    Detail view for posts and children
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'cms/detail.html'
 | 
			
		||||
 | 
			
		||||
    sections = []
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, sections = None, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.sections = sections or []
 | 
			
		||||
 | 
			
		||||
    def get_queryset (self, **kwargs):
 | 
			
		||||
        if self.model:
 | 
			
		||||
            return super().get_queryset(**kwargs).filter(published = True)
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    def get_object (self, **kwargs):
 | 
			
		||||
        if self.model:
 | 
			
		||||
            object = super().get_object(**kwargs)
 | 
			
		||||
            if object.published:
 | 
			
		||||
                return object
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    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, object = self.object)
 | 
			
		||||
                    for section in self.sections
 | 
			
		||||
            ]
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ViewSet:
 | 
			
		||||
    """
 | 
			
		||||
    A ViewSet is a class helper that groups detail and list views that can be
 | 
			
		||||
    used to generate views and routes given a model and a name used for the
 | 
			
		||||
    routing.
 | 
			
		||||
    """
 | 
			
		||||
    model = None
 | 
			
		||||
    list_view = PostListView
 | 
			
		||||
    list_routes = []
 | 
			
		||||
 | 
			
		||||
    detail_view = PostDetailView
 | 
			
		||||
    detail_sections = []
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, website = None):
 | 
			
		||||
        self.detail_sections = [
 | 
			
		||||
            section()
 | 
			
		||||
                for section in self.detail_sections
 | 
			
		||||
        ]
 | 
			
		||||
        self.detail_view = self.detail_view.as_view(
 | 
			
		||||
            model = self.model,
 | 
			
		||||
            sections = self.detail_sections,
 | 
			
		||||
            website = website,
 | 
			
		||||
        )
 | 
			
		||||
        self.list_view = self.list_view.as_view(
 | 
			
		||||
            model = self.model,
 | 
			
		||||
            website = website,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.urls = [ route.as_url(self.model, self.list_view)
 | 
			
		||||
                            for route in self.list_routes ] + \
 | 
			
		||||
                      [ routes.DetailRoute.as_url(self.model, self.detail_view ) ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Menu (View):
 | 
			
		||||
    template_name = 'cms/menu.html'
 | 
			
		||||
 | 
			
		||||
    name = ''
 | 
			
		||||
    enabled = True
 | 
			
		||||
    classes = ''
 | 
			
		||||
    position = ''   # top, left, bottom, right, header, footer
 | 
			
		||||
    sections = None
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.name = self.name or ('menu_' + self.position)
 | 
			
		||||
 | 
			
		||||
    def get_context_data (self, **kwargs):
 | 
			
		||||
        return {
 | 
			
		||||
            'name': self.name,
 | 
			
		||||
            'classes': self.classes,
 | 
			
		||||
            'position': self.position,
 | 
			
		||||
            'sections': [
 | 
			
		||||
                section.get(self.request, object = None)
 | 
			
		||||
                    for section in self.sections
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    def get (self, request, **kwargs):
 | 
			
		||||
        self.request = request
 | 
			
		||||
        context = self.get_context_data(**kwargs)
 | 
			
		||||
        return render_to_string(self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Section (View):
 | 
			
		||||
    """
 | 
			
		||||
    Base class for sections. Sections are view that can be used in detail view
 | 
			
		||||
    in order to have extra content about a post.
 | 
			
		||||
    """
 | 
			
		||||
    template_name = 'cms/section.html'
 | 
			
		||||
    require_object = False
 | 
			
		||||
    object = None
 | 
			
		||||
    classes = ''
 | 
			
		||||
    title = ''
 | 
			
		||||
    content = ''
 | 
			
		||||
    header = ''
 | 
			
		||||
    bottom = ''
 | 
			
		||||
 | 
			
		||||
    def get_context_data (self, **kwargs):
 | 
			
		||||
        context = {
 | 
			
		||||
            'title': self.title,
 | 
			
		||||
            'header': self.header,
 | 
			
		||||
            'content': self.content,
 | 
			
		||||
            'bottom': self.bottom,
 | 
			
		||||
            'classes': self.classes,
 | 
			
		||||
        }
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    def get (self, request, **kwargs):
 | 
			
		||||
        self.object = kwargs.get('object') or self.object
 | 
			
		||||
        self.request = request
 | 
			
		||||
        context = self.get_context_data(**kwargs)
 | 
			
		||||
        return render_to_string(self.template_name, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ListSection (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
 | 
			
		||||
 | 
			
		||||
        def __init__ (self, icon, title = None, text = None):
 | 
			
		||||
            self.icon = icon
 | 
			
		||||
            self.title = title
 | 
			
		||||
            self.text = text
 | 
			
		||||
 | 
			
		||||
    use_icons = True
 | 
			
		||||
    icon_size = '32x32'
 | 
			
		||||
    template_name = 'cms/section_list.html'
 | 
			
		||||
 | 
			
		||||
    def get_object_list (self):
 | 
			
		||||
        return []
 | 
			
		||||
 | 
			
		||||
    def get_context_data (self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        context.update({
 | 
			
		||||
            'classes': context.get('classes') + ' section_list',
 | 
			
		||||
            'icon_size': self.icon_size,
 | 
			
		||||
            'object_list': self.get_object_list(),
 | 
			
		||||
        })
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UrlListSection (ListSection):
 | 
			
		||||
    classes = 'section_urls'
 | 
			
		||||
    targets = None
 | 
			
		||||
 | 
			
		||||
    def get_object_list (self, request, **kwargs):
 | 
			
		||||
        return [
 | 
			
		||||
            ListSection.Item(
 | 
			
		||||
                target.image or None,
 | 
			
		||||
                '<a href="{}">{}</a>'.format(target.detail_url(), target.title)
 | 
			
		||||
            )
 | 
			
		||||
            for target in self.targets
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PostListSection (PostListView):
 | 
			
		||||
    route = None
 | 
			
		||||
    model = None
 | 
			
		||||
    embed = True
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_kwargs (self, request, **kwargs):
 | 
			
		||||
        return kwargs
 | 
			
		||||
 | 
			
		||||
    def dispatch (self, request, *args, **kwargs):
 | 
			
		||||
        kwargs = self.get_kwargs(kwargs)
 | 
			
		||||
        response = super().dispatch(request, *args, **kwargs)
 | 
			
		||||
        return str(response.content)
 | 
			
		||||
 | 
			
		||||
# TODO:
 | 
			
		||||
# - get_title: pass object / queryset
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,40 +0,0 @@
 | 
			
		||||
import cms.routes as routes
 | 
			
		||||
 | 
			
		||||
class Website:
 | 
			
		||||
    name = ''
 | 
			
		||||
    domain = ''
 | 
			
		||||
    logo = None
 | 
			
		||||
    menus = None
 | 
			
		||||
    router = None
 | 
			
		||||
 | 
			
		||||
    def __init__ (self, **kwargs):
 | 
			
		||||
        self.__dict__.update(kwargs)
 | 
			
		||||
        if not self.router:
 | 
			
		||||
            self.router = routes.Router()
 | 
			
		||||
 | 
			
		||||
    def register_set (self, view_set):
 | 
			
		||||
        view_set = view_set(website = self)
 | 
			
		||||
        self.router.register_set(view_set)
 | 
			
		||||
 | 
			
		||||
    def get_menu (self, position):
 | 
			
		||||
        for menu in self.menus:
 | 
			
		||||
            if menu.enabled and menu.position == position:
 | 
			
		||||
                return menu
 | 
			
		||||
 | 
			
		||||
    def get_top_menu (self):
 | 
			
		||||
        return self.get_menu('top')
 | 
			
		||||
 | 
			
		||||
    def get_left_menu (self):
 | 
			
		||||
        return self.get_menu('left')
 | 
			
		||||
 | 
			
		||||
    def get_bottom_menu (self):
 | 
			
		||||
        return self.get_menu('bottom')
 | 
			
		||||
 | 
			
		||||
    def get_right_menu (self):
 | 
			
		||||
        return self.get_menu('right')
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def urls (self):
 | 
			
		||||
        return self.router.get_urlpatterns()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user