forked from rc/aircox
		
	split website and cms; work on sections
This commit is contained in:
		
							
								
								
									
										3
									
								
								cms/admin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								cms/admin.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					from django.contrib import admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Register your models here.
 | 
				
			||||||
							
								
								
									
										154
									
								
								cms/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								cms/models.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					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_save
 | 
				
			||||||
 | 
					from django.dispatch import receiver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Using a separate thread helps for routing, by avoiding to specify an
 | 
				
			||||||
 | 
					# additional argument to get the second model that implies to find it by
 | 
				
			||||||
 | 
					# the name that can be non user-friendly, like /thread/relatedpost/id
 | 
				
			||||||
 | 
					class Thread (models.Model):
 | 
				
			||||||
 | 
					    post_type = models.ForeignKey(ContentType)
 | 
				
			||||||
 | 
					    post_id = models.PositiveIntegerField()
 | 
				
			||||||
 | 
					    post = GenericForeignKey('post_type', 'post_id')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get (cl, model, **kwargs):
 | 
				
			||||||
 | 
					        post_type = ContentType.objects.get_for_model(model)
 | 
				
			||||||
 | 
					        return cl.objects.get(post_type__pk = post_type.id,
 | 
				
			||||||
 | 
					                              **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def filter (cl, model, **kwargs):
 | 
				
			||||||
 | 
					        post_type = ContentType.objects.get_for_model(model)
 | 
				
			||||||
 | 
					        return cl.objects.filter(post_type__pk = post_type.id,
 | 
				
			||||||
 | 
					                              **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def exclude (cl, model, **kwargs):
 | 
				
			||||||
 | 
					        post_type = ContentType.objects.get_for_model(model)
 | 
				
			||||||
 | 
					        return cl.objects.exclude(post_type__pk = post_type.id,
 | 
				
			||||||
 | 
					                              **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
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    public = models.BooleanField(
 | 
				
			||||||
 | 
					        verbose_name = _('public'),
 | 
				
			||||||
 | 
					        default = True
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    image = models.ImageField(
 | 
				
			||||||
 | 
					        blank = True, null = True
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    title = ''
 | 
				
			||||||
 | 
					    content = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@receiver(post_save)
 | 
				
			||||||
 | 
					def on_new_post (sender, instance, created, *args, **kwargs):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Signal handler to create a thread that is attached to the newly post
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if not issubclass(sender, Post) or not created:
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    thread = Thread(post = instance)
 | 
				
			||||||
 | 
					    thread.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Article (Post):
 | 
				
			||||||
 | 
					    title = models.CharField(
 | 
				
			||||||
 | 
					        _('title'),
 | 
				
			||||||
 | 
					        max_length = 128,
 | 
				
			||||||
 | 
					        blank = False, null = False
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    content = models.TextField(
 | 
				
			||||||
 | 
					        _('content'),
 | 
				
			||||||
 | 
					        blank = False, null = False
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mapping = rel.get('mapping')
 | 
				
			||||||
 | 
					        if mapping:
 | 
				
			||||||
 | 
					            def get_prop (name, related_name):
 | 
				
			||||||
 | 
					                return property(related_name) if callable(related_name) \
 | 
				
			||||||
 | 
					                        else property(lambda self:
 | 
				
			||||||
 | 
					                                        getattr(self.related, related_name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            attrs.update({
 | 
				
			||||||
 | 
					                name: get_prop(name, related_name)
 | 
				
			||||||
 | 
					                    for name, related_name in mapping.items()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not '__str__' in attrs:
 | 
				
			||||||
 | 
					            attrs['__str__'] = lambda self: str(self.related)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return super().__new__(cls, name, bases, attrs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        abstract = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Relation:
 | 
				
			||||||
 | 
					        related_model = None
 | 
				
			||||||
 | 
					        mapping = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -42,8 +42,7 @@ class Route:
 | 
				
			|||||||
        is_list = False     # route is for a list
 | 
					        is_list = False     # route is for a list
 | 
				
			||||||
        url_args = []       # arguments passed from the url [ (name : regex),... ]
 | 
					        url_args = []       # arguments passed from the url [ (name : regex),... ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__ (self, model, view, view_kwargs = None,
 | 
					    def __init__ (self, model, view, view_kwargs = None):
 | 
				
			||||||
                  base_name = None):
 | 
					 | 
				
			||||||
        self.model = model
 | 
					        self.model = model
 | 
				
			||||||
        self.view = view
 | 
					        self.view = view
 | 
				
			||||||
        self.view_kwargs = view_kwargs
 | 
					        self.view_kwargs = view_kwargs
 | 
				
			||||||
@ -54,11 +53,7 @@ class Route:
 | 
				
			|||||||
        _meta.update(self.Meta.__dict__)
 | 
					        _meta.update(self.Meta.__dict__)
 | 
				
			||||||
        self._meta = _meta
 | 
					        self._meta = _meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not base_name:
 | 
					        self.base_name = model._meta.verbose_name_plural.lower()
 | 
				
			||||||
            base_name = model._meta.verbose_name_plural if _meta['is_list'] \
 | 
					 | 
				
			||||||
                    else model._meta.verbose_name
 | 
					 | 
				
			||||||
            base_name = base_name.title().lower()
 | 
					 | 
				
			||||||
        self.base_name = base_name
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_queryset (self, request, **kwargs):
 | 
					    def get_queryset (self, request, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@ -75,8 +70,12 @@ class Route:
 | 
				
			|||||||
    def get_url (self):
 | 
					    def get_url (self):
 | 
				
			||||||
        pattern = '^{}/{}'.format(self.base_name, self.Meta.name)
 | 
					        pattern = '^{}/{}'.format(self.base_name, self.Meta.name)
 | 
				
			||||||
        if self._meta['url_args']:
 | 
					        if self._meta['url_args']:
 | 
				
			||||||
            url_args = '/'.join([ '(?P<{}>{})'.format(arg, expr) \
 | 
					            url_args = '/'.join([
 | 
				
			||||||
                                    for arg, expr in self._meta['url_args']
 | 
					                '(?P<{}>{}){}'.format(
 | 
				
			||||||
 | 
					                    arg, expr,
 | 
				
			||||||
 | 
					                    (optional and optional[0] and '?') or ''
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                for arg, expr, *optional in self._meta['url_args']
 | 
				
			||||||
            ])
 | 
					            ])
 | 
				
			||||||
            pattern += '/' + url_args
 | 
					            pattern += '/' + url_args
 | 
				
			||||||
        pattern += '/?$'
 | 
					        pattern += '/?$'
 | 
				
			||||||
@ -87,7 +86,8 @@ class Route:
 | 
				
			|||||||
        if self.view_kwargs:
 | 
					        if self.view_kwargs:
 | 
				
			||||||
            kwargs.update(self.view_kwargs)
 | 
					            kwargs.update(self.view_kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return url(pattern, self.view, kwargs = kwargs, name = '{}')
 | 
					        return url(pattern, self.view, kwargs = kwargs,
 | 
				
			||||||
 | 
					                   name = self.base_name + '_' + self.Meta.name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DetailRoute (Route):
 | 
					class DetailRoute (Route):
 | 
				
			||||||
@ -96,19 +96,28 @@ class DetailRoute (Route):
 | 
				
			|||||||
        is_list = False
 | 
					        is_list = False
 | 
				
			||||||
        url_args = [
 | 
					        url_args = [
 | 
				
			||||||
            ('pk', '[0-9]+'),
 | 
					            ('pk', '[0-9]+'),
 | 
				
			||||||
            ('slug', '(\w|-|_)*'),
 | 
					            ('slug', '(\w|-|_)+', True),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get (self, request, **kwargs):
 | 
					    def get (self, request, **kwargs):
 | 
				
			||||||
        return self.model.objects.get(pk = int(kwargs['pk']))
 | 
					        return self.model.objects.get(pk = int(kwargs['pk']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AllRoute (Route):
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        name = 'all'
 | 
				
			||||||
 | 
					        is_list = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_queryset (self, request, **kwargs):
 | 
				
			||||||
 | 
					        return self.model.objects.all()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ThreadRoute (Route):
 | 
					class ThreadRoute (Route):
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        name = 'thread'
 | 
					        name = 'thread'
 | 
				
			||||||
        is_list = True
 | 
					        is_list = True
 | 
				
			||||||
        url_args = [
 | 
					        url_args = [
 | 
				
			||||||
            ('pk', '[0-9]+')
 | 
					            ('pk', '[0-9]+'),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_queryset (self, request, **kwargs):
 | 
					    def get_queryset (self, request, **kwargs):
 | 
				
			||||||
@ -9,8 +9,7 @@
 | 
				
			|||||||
<div class="post_list {{ classes }}">
 | 
					<div class="post_list {{ classes }}">
 | 
				
			||||||
{% for post in object_list %}
 | 
					{% for post in object_list %}
 | 
				
			||||||
    <a class="post_item"
 | 
					    <a class="post_item"
 | 
				
			||||||
       href="{{ post.get_detail_url }}">
 | 
					       href="{{ post.detail_url }}">
 | 
				
			||||||
 | 
					 | 
				
			||||||
        {% if 'date' in list.fields or 'time' in list.fields %}
 | 
					        {% if 'date' in list.fields or 'time' in list.fields %}
 | 
				
			||||||
        <time datetime="{{ post.date }}" class="post_datetime">
 | 
					        <time datetime="{{ post.date }}" class="post_datetime">
 | 
				
			||||||
            {% if 'date' in list.fields %}
 | 
					            {% if 'date' in list.fields %}
 | 
				
			||||||
							
								
								
									
										193
									
								
								cms/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								cms/views.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,193 @@
 | 
				
			|||||||
 | 
					from django.shortcuts import render
 | 
				
			||||||
 | 
					from django.template.loader import render_to_string
 | 
				
			||||||
 | 
					from django.views.generic import ListView
 | 
				
			||||||
 | 
					from django.views.generic import DetailView
 | 
				
			||||||
 | 
					from django.core import serializers
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext as _, ugettext_lazy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cms.routes as routes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Section (DetailView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    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'
 | 
				
			||||||
 | 
					    classes = ''
 | 
				
			||||||
 | 
					    title = ''
 | 
				
			||||||
 | 
					    content = ''
 | 
				
			||||||
 | 
					    header = ''
 | 
				
			||||||
 | 
					    bottom = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
 | 
					        context = super().get_context_data(**kwargs)
 | 
				
			||||||
 | 
					        context.update({
 | 
				
			||||||
 | 
					            'title': self.title,
 | 
				
			||||||
 | 
					            'header': self.header,
 | 
				
			||||||
 | 
					            'content': self.content,
 | 
				
			||||||
 | 
					            'bottom': self.bottom,
 | 
				
			||||||
 | 
					            'classes': self.classes,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get (self, parent, request, object = None, **kwargs):
 | 
				
			||||||
 | 
					        print(type(object))
 | 
				
			||||||
 | 
					        self.object = object
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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['classes'] += ' section_list'
 | 
				
			||||||
 | 
					        context['object_list'] = self.get_object_list()
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PostListView (ListView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    List view for posts and children
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    class Query:
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Request availables parameters
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        embed = False
 | 
				
			||||||
 | 
					        exclude = None
 | 
				
			||||||
 | 
					        order = 'desc'
 | 
				
			||||||
 | 
					        reverse = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def __init__ (self, query):
 | 
				
			||||||
 | 
					            my_class = self.__class__
 | 
				
			||||||
 | 
					            if type(query) is my_class:
 | 
				
			||||||
 | 
					                self.__dict__.update(query.__dict__)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if type(query) is not dict:
 | 
				
			||||||
 | 
					                query = query.__dict__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.__dict__ = { k: v for k,v in query.items() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template_name = 'cms/list.html'
 | 
				
			||||||
 | 
					    allow_empty = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    model = None
 | 
				
			||||||
 | 
					    query = None
 | 
				
			||||||
 | 
					    fields = [ 'date', 'time', 'image', 'title', 'content' ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__ (self, *args, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        if self.query:
 | 
				
			||||||
 | 
					            self.query = Query(self.query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_queryset (self):
 | 
				
			||||||
 | 
					        route = self.kwargs['route']
 | 
				
			||||||
 | 
					        qs = route.get_queryset(self.request, **self.kwargs)
 | 
				
			||||||
 | 
					        qs = qs.filter(public = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        query = self.query or PostListView.Query(self.request.GET)
 | 
				
			||||||
 | 
					        if query.exclude:
 | 
				
			||||||
 | 
					            qs = qs.exclude(id = int(exclude))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if query.order == 'asc':
 | 
				
			||||||
 | 
					            qs.order_by('date', 'id')
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            qs.order_by('-date', '-id')
 | 
				
			||||||
 | 
					        return qs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
 | 
					        context = super().get_context_data(**kwargs)
 | 
				
			||||||
 | 
					        context.update({
 | 
				
			||||||
 | 
					            'list': self
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PostDetailView (DetailView):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    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(public = True)
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_object (self, **kwargs):
 | 
				
			||||||
 | 
					        if self.model:
 | 
				
			||||||
 | 
					            object = super().get_object(**kwargs)
 | 
				
			||||||
 | 
					            if object.public:
 | 
				
			||||||
 | 
					                return object
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_context_data (self, **kwargs):
 | 
				
			||||||
 | 
					        context = super().get_context_data(**kwargs)
 | 
				
			||||||
 | 
					        context.update({
 | 
				
			||||||
 | 
					            'sections': [
 | 
				
			||||||
 | 
					                section.get(self, 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):
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.list_view = self.list_view.as_view(
 | 
				
			||||||
 | 
					            model = self.model
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.routes = [ route(self.model, self.list_view)
 | 
				
			||||||
 | 
					                            for route in self.list_routes ] + \
 | 
				
			||||||
 | 
					                      [ routes.DetailRoute(self.model, self.detail_view ) ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,7 +70,7 @@ class Track (Description):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return ' '.join([self.artist, ':', self.title])
 | 
					        return ' '.join([self.artist, ':', self.name ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _('Track')
 | 
					        verbose_name = _('Track')
 | 
				
			||||||
@ -178,6 +178,7 @@ class Schedule (models.Model):
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    rerun = models.ForeignKey(
 | 
					    rerun = models.ForeignKey(
 | 
				
			||||||
        'self',
 | 
					        'self',
 | 
				
			||||||
 | 
					        verbose_name = _('rerun'),
 | 
				
			||||||
        blank = True, null = True,
 | 
					        blank = True, null = True,
 | 
				
			||||||
        help_text = "Schedule of a rerun of this one",
 | 
					        help_text = "Schedule of a rerun of this one",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
@ -265,7 +266,7 @@ class Schedule (models.Model):
 | 
				
			|||||||
        """
 | 
					        """
 | 
				
			||||||
        dates = self.dates_of_month(date)
 | 
					        dates = self.dates_of_month(date)
 | 
				
			||||||
        saved = Diffusion.objects.filter(date__in = dates,
 | 
					        saved = Diffusion.objects.filter(date__in = dates,
 | 
				
			||||||
                                         program = self.parent)
 | 
					                                         program = self.program)
 | 
				
			||||||
        diffusions = []
 | 
					        diffusions = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # existing diffusions
 | 
					        # existing diffusions
 | 
				
			||||||
@ -282,13 +283,13 @@ class Schedule (models.Model):
 | 
				
			|||||||
                first_date -= self.date - self.rerun.date
 | 
					                first_date -= self.date - self.rerun.date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            episode = Episode.objects.filter(date = first_date,
 | 
					            episode = Episode.objects.filter(date = first_date,
 | 
				
			||||||
                                             parent = self.parent)
 | 
					                                             program = self.program)
 | 
				
			||||||
            episode = episode[0] if episode.count() else None
 | 
					            episode = episode[0] if episode.count() else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            diffusions.append(Diffusion(
 | 
					            diffusions.append(Diffusion(
 | 
				
			||||||
                                 episode = episode,
 | 
					                                 episode = episode,
 | 
				
			||||||
                                 program = self.parent,
 | 
					                                 program = self.program,
 | 
				
			||||||
                                 stream = self.parent.stream,
 | 
					                                 stream = self.program.stream,
 | 
				
			||||||
                                 type = Diffusion.Type['unconfirmed'],
 | 
					                                 type = Diffusion.Type['unconfirmed'],
 | 
				
			||||||
                                 date = date,
 | 
					                                 date = date,
 | 
				
			||||||
                             ))
 | 
					                             ))
 | 
				
			||||||
@ -297,7 +298,7 @@ class Schedule (models.Model):
 | 
				
			|||||||
    def __str__ (self):
 | 
					    def __str__ (self):
 | 
				
			||||||
        frequency = [ x for x,y in Schedule.Frequency.items()
 | 
					        frequency = [ x for x,y in Schedule.Frequency.items()
 | 
				
			||||||
                        if y == self.frequency ]
 | 
					                        if y == self.frequency ]
 | 
				
			||||||
        return self.parent.title + ': ' + frequency[0]
 | 
					        return self.program.name + ': ' + frequency[0] + ' (' + str(self.date) + ')'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _('Schedule')
 | 
					        verbose_name = _('Schedule')
 | 
				
			||||||
@ -339,12 +340,12 @@ class Diffusion (models.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def save (self, *args, **kwargs):
 | 
					    def save (self, *args, **kwargs):
 | 
				
			||||||
        if self.episode: # FIXME self.episode or kwargs['episode']
 | 
					        if self.episode: # FIXME self.episode or kwargs['episode']
 | 
				
			||||||
            self.program = self.episode.parent
 | 
					            self.program = self.episode.program
 | 
				
			||||||
        # check type against stream's type
 | 
					        # check type against stream's type
 | 
				
			||||||
        super(Diffusion, self).save(*args, **kwargs)
 | 
					        super(Diffusion, self).save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__ (self):
 | 
					    def __str__ (self):
 | 
				
			||||||
        return self.program.title + ' on ' + str(self.date) \
 | 
					        return self.program.name + ' on ' + str(self.date) \
 | 
				
			||||||
               + str(self.type)
 | 
					               + str(self.type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
@ -406,13 +407,13 @@ class Program (Description):
 | 
				
			|||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def path (self):
 | 
					    def path (self):
 | 
				
			||||||
        return os.path.join(settings.AIRCOX_PROGRAMS_DIR,
 | 
					        return os.path.join(settings.AIRCOX_PROGRAMS_DIR,
 | 
				
			||||||
                            slugify(self.title + '_' + str(self.id)) )
 | 
					                            slugify(self.name + '_' + str(self.id)) )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def find_schedule (self, date):
 | 
					    def find_schedule (self, date):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return the first schedule that matches a given date
 | 
					        Return the first schedule that matches a given date
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        schedules = Schedule.objects.filter(parent = self)
 | 
					        schedules = Schedule.objects.filter(program = self)
 | 
				
			||||||
        for schedule in schedules:
 | 
					        for schedule in schedules:
 | 
				
			||||||
            if schedule.match(date, check_time = False):
 | 
					            if schedule.match(date, check_time = False):
 | 
				
			||||||
                return schedule
 | 
					                return schedule
 | 
				
			||||||
@ -421,7 +422,7 @@ class Program (Description):
 | 
				
			|||||||
class Episode (Description):
 | 
					class Episode (Description):
 | 
				
			||||||
    program = models.ForeignKey(
 | 
					    program = models.ForeignKey(
 | 
				
			||||||
        Program,
 | 
					        Program,
 | 
				
			||||||
        verbose_name = _('parent'),
 | 
					        verbose_name = _('program'),
 | 
				
			||||||
        help_text = _('parent program'),
 | 
					        help_text = _('parent program'),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    sounds = models.ManyToManyField(
 | 
					    sounds = models.ManyToManyField(
 | 
				
			||||||
 | 
				
			|||||||
@ -28,8 +28,8 @@ def add_inline (base_model, post_model, prepend = False):
 | 
				
			|||||||
    registry[base_model].inlines = inlines
 | 
					    registry[base_model].inlines = inlines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_inline(programs.Program, ProgramPost)
 | 
					add_inline(programs.Program, Program)
 | 
				
			||||||
add_inline(programs.Episode, EpisodePost)
 | 
					add_inline(programs.Episode, Episode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#class ArticleAdmin (DescriptionAdmin):
 | 
					#class ArticleAdmin (DescriptionAdmin):
 | 
				
			||||||
 | 
				
			|||||||
@ -1,169 +1,21 @@
 | 
				
			|||||||
from django.db import models
 | 
					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.translation import ugettext as _, ugettext_lazy
 | 
					 | 
				
			||||||
from django.utils import timezone
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from django.db.models.signals import post_save
 | 
					 | 
				
			||||||
from django.dispatch import receiver
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from cms.models import RelatedPost
 | 
				
			||||||
import programs.models as programs
 | 
					import programs.models as programs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Program (RelatedPost):
 | 
				
			||||||
class Thread (models.Model):
 | 
					    class Relation:
 | 
				
			||||||
    post_type = models.ForeignKey(ContentType)
 | 
					        related_model = programs.Program
 | 
				
			||||||
    post_id = models.PositiveIntegerField()
 | 
					        mapping = {
 | 
				
			||||||
    post = GenericForeignKey('post_type', 'post_id')
 | 
					            'title': 'name',
 | 
				
			||||||
 | 
					            'content': 'description',
 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def get (cl, model, **kwargs):
 | 
					 | 
				
			||||||
        post_type = ContentType.objects.get_for_model(model)
 | 
					 | 
				
			||||||
        return cl.objects.get(post_type__pk = post_type.id,
 | 
					 | 
				
			||||||
                              **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def filter (cl, model, **kwargs):
 | 
					 | 
				
			||||||
        post_type = ContentType.objects.get_for_model(model)
 | 
					 | 
				
			||||||
        return cl.objects.filter(post_type__pk = post_type.id,
 | 
					 | 
				
			||||||
                              **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def exclude (cl, model, **kwargs):
 | 
					 | 
				
			||||||
        post_type = ContentType.objects.get_for_model(model)
 | 
					 | 
				
			||||||
        return cl.objects.exclude(post_type__pk = post_type.id,
 | 
					 | 
				
			||||||
                              **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__ (self):
 | 
					 | 
				
			||||||
        return str(self.post)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class BasePost (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
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    public = models.BooleanField(
 | 
					 | 
				
			||||||
        verbose_name = _('public'),
 | 
					 | 
				
			||||||
        default = True
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    image = models.ImageField(
 | 
					 | 
				
			||||||
        blank = True, null = True
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    title = ''
 | 
					 | 
				
			||||||
    content = ''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class Meta:
 | 
					 | 
				
			||||||
        abstract = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@receiver(post_save)
 | 
					 | 
				
			||||||
def on_new_post (sender, instance, created, *args, **kwargs):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Signal handler to create a thread that is attached to the newly post
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    if not issubclass(sender, BasePost) or not created:
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    thread = Thread(post = instance)
 | 
					 | 
				
			||||||
    thread.save()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Post (BasePost):
 | 
					 | 
				
			||||||
    class Meta:
 | 
					 | 
				
			||||||
        abstract = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def create_related_post (model, maps):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Create a subclass of BasePost model, that binds the common-fields
 | 
					 | 
				
			||||||
        using the given maps. The maps' keys are the property to change, and
 | 
					 | 
				
			||||||
        its value is the target model's attribute (or a callable)
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        class Meta:
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        attrs = {
 | 
					 | 
				
			||||||
            '__module__': BasePost.__module__,
 | 
					 | 
				
			||||||
            'Meta': Meta,
 | 
					 | 
				
			||||||
            'related': models.ForeignKey(model),
 | 
					 | 
				
			||||||
            '__str__': lambda self: str(self.related)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def get_prop (name, related_name):
 | 
					class Episode (RelatedPost):
 | 
				
			||||||
            return property(related_name) if callable(related_name) \
 | 
					    class Relation:
 | 
				
			||||||
                    else property(lambda self: getattr(self.related, related_name))
 | 
					        related_model = programs.Episode
 | 
				
			||||||
 | 
					        mapping = {
 | 
				
			||||||
        attrs.update({
 | 
					 | 
				
			||||||
            name: get_prop(name, related_name)
 | 
					 | 
				
			||||||
                for name, related_name in maps.items()
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        return type(model.__name__ + 'Post', (BasePost,), attrs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Article (BasePost):
 | 
					 | 
				
			||||||
    title = models.CharField(
 | 
					 | 
				
			||||||
        _('title'),
 | 
					 | 
				
			||||||
        max_length = 128,
 | 
					 | 
				
			||||||
        blank = False, null = False
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    content = models.TextField(
 | 
					 | 
				
			||||||
        _('content'),
 | 
					 | 
				
			||||||
        blank = False, null = False
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    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')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ProgramPost = Post.create_related_post(programs.Program, {
 | 
					 | 
				
			||||||
            'title': 'name',
 | 
					            'title': 'name',
 | 
				
			||||||
            'content': 'description',
 | 
					            'content': 'description',
 | 
				
			||||||
               })
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EpisodePost = Post.create_related_post(programs.Episode, {
 | 
					 | 
				
			||||||
                    'title': 'name',
 | 
					 | 
				
			||||||
                    'content': 'description',
 | 
					 | 
				
			||||||
               })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#class MenuItem ():
 | 
					 | 
				
			||||||
#    Menu = {
 | 
					 | 
				
			||||||
#        'top':      0x00,
 | 
					 | 
				
			||||||
#        'sidebar':  0x01,
 | 
					 | 
				
			||||||
#        'bottom':   0x02,
 | 
					 | 
				
			||||||
#    }
 | 
					 | 
				
			||||||
#    for key, value in Type.items():
 | 
					 | 
				
			||||||
#        ugettext_lazy(key)
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
#    parent = models.ForeignKey(
 | 
					 | 
				
			||||||
#        'self',
 | 
					 | 
				
			||||||
#        blank = True, null = True
 | 
					 | 
				
			||||||
#    )
 | 
					 | 
				
			||||||
#    menu = models.SmallIntegerField(
 | 
					 | 
				
			||||||
#    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,40 +2,42 @@ from django.conf.urls import url, include
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from website.models import *
 | 
					from website.models import *
 | 
				
			||||||
from website.views import *
 | 
					from website.views import *
 | 
				
			||||||
from website.routes import *
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from cms.models import Article
 | 
				
			||||||
 | 
					from cms.views import ViewSet
 | 
				
			||||||
 | 
					from cms.routes import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProgramSet (ViewSet):
 | 
					class ProgramSet (ViewSet):
 | 
				
			||||||
    model = ProgramPost
 | 
					    model = Program
 | 
				
			||||||
    name = 'programs'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    list_routes = [
 | 
					    list_routes = [
 | 
				
			||||||
 | 
					        AllRoute,
 | 
				
			||||||
        ThreadRoute,
 | 
					        ThreadRoute,
 | 
				
			||||||
        SearchRoute,
 | 
					        SearchRoute,
 | 
				
			||||||
        DateRoute,
 | 
					        DateRoute,
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detail_sections = [
 | 
				
			||||||
 | 
					        ScheduleSection
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class EpisodeSet (ViewSet):
 | 
					class EpisodeSet (ViewSet):
 | 
				
			||||||
    model = EpisodePost
 | 
					    model = Episode
 | 
				
			||||||
    name = 'episodes'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    list_routes = [
 | 
					    list_routes = [
 | 
				
			||||||
 | 
					        AllRoute,
 | 
				
			||||||
        ThreadRoute,
 | 
					        ThreadRoute,
 | 
				
			||||||
        SearchRoute,
 | 
					        SearchRoute,
 | 
				
			||||||
        DateRoute,
 | 
					        DateRoute,
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
class ArticleSet (ViewSet):
 | 
					class ArticleSet (ViewSet):
 | 
				
			||||||
    model = Article
 | 
					    model = Article
 | 
				
			||||||
    list_routes = [
 | 
					    list_routes = [
 | 
				
			||||||
 | 
					        AllRoute,
 | 
				
			||||||
        ThreadRoute,
 | 
					        ThreadRoute,
 | 
				
			||||||
        SearchRoute,
 | 
					        SearchRoute,
 | 
				
			||||||
        DateRoute,
 | 
					        DateRoute,
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
router = Router()
 | 
					router = Router()
 | 
				
			||||||
router.register_set(ProgramSet())
 | 
					router.register_set(ProgramSet())
 | 
				
			||||||
router.register_set(EpisodeSet())
 | 
					router.register_set(EpisodeSet())
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										171
									
								
								website/views.py
									
									
									
									
									
								
							
							
						
						
									
										171
									
								
								website/views.py
									
									
									
									
									
								
							@ -5,165 +5,32 @@ from django.views.generic import DetailView
 | 
				
			|||||||
from django.core import serializers
 | 
					from django.core import serializers
 | 
				
			||||||
from django.utils.translation import ugettext as _, ugettext_lazy
 | 
					from django.utils.translation import ugettext as _, ugettext_lazy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from website.models import *
 | 
					import programs.models as programs
 | 
				
			||||||
from website.routes import *
 | 
					from cms.views import ListSection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PostListView (ListView):
 | 
					class PlaylistSection (ListSection):
 | 
				
			||||||
    """
 | 
					    title = _('Playlist')
 | 
				
			||||||
    List view for posts and children
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    class Query:
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Request availables parameters
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        embed = False
 | 
					 | 
				
			||||||
        exclude = None
 | 
					 | 
				
			||||||
        order = 'desc'
 | 
					 | 
				
			||||||
        reverse = False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def __init__ (self, query):
 | 
					    def get_object_list (self):
 | 
				
			||||||
            my_class = self.__class__
 | 
					        tracks = programs.Track.objects \
 | 
				
			||||||
            if type(query) is my_class:
 | 
					                     .filter(episode = self.object) \
 | 
				
			||||||
                self.__dict__.update(query.__dict__)
 | 
					                     .order_by('position')
 | 
				
			||||||
                return
 | 
					        return [ ListSection.Item(None, track.title, track.artist)
 | 
				
			||||||
 | 
					                    for track in tracks ]
 | 
				
			||||||
            if type(query) is not dict:
 | 
					 | 
				
			||||||
                query = query.__dict__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            self.__dict__ = { k: v for k,v in query.items() }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    template_name = 'website/list.html'
 | 
					 | 
				
			||||||
    allow_empty = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    model = None
 | 
					 | 
				
			||||||
    query = None
 | 
					 | 
				
			||||||
    fields = [ 'date', 'time', 'image', 'title', 'content' ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__ (self, *args, **kwargs):
 | 
					 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					 | 
				
			||||||
        if self.query:
 | 
					 | 
				
			||||||
            self.query = Query(self.query)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_queryset (self):
 | 
					 | 
				
			||||||
        route = self.kwargs['route']
 | 
					 | 
				
			||||||
        qs = route.get_queryset(self.request, **self.kwargs)
 | 
					 | 
				
			||||||
        qs = qs.filter(public = True)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        query = self.query or PostListView.Query(self.request.GET)
 | 
					 | 
				
			||||||
        if query.exclude:
 | 
					 | 
				
			||||||
            qs = qs.exclude(id = int(exclude))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if query.order == 'asc':
 | 
					 | 
				
			||||||
            qs.order_by('date', 'id')
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            qs.order_by('-date', '-id')
 | 
					 | 
				
			||||||
        return qs
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_context_data (self, **kwargs):
 | 
					class ScheduleSection (ListSection):
 | 
				
			||||||
        context = super().get_context_data(**kwargs)
 | 
					    title = _('Schedule')
 | 
				
			||||||
        context.update({
 | 
					 | 
				
			||||||
            'list': self
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return context
 | 
					    def get_object_list (self):
 | 
				
			||||||
 | 
					        scheds = programs.Schedule.objects \
 | 
				
			||||||
 | 
					                    .filter(program = self.object.pk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
class PostDetailView (DetailView):
 | 
					            ListSection.Item(None, sched.get_frequency_display(),
 | 
				
			||||||
    """
 | 
					                             _('rerun') if sched.rerun else None)
 | 
				
			||||||
    Detail view for posts and children
 | 
					            for sched in scheds
 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    template_name = 'website/detail.html'
 | 
					 | 
				
			||||||
    sections = None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__ (self, sections = None, *args, **kwargs):
 | 
					 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_queryset (self, **kwargs):
 | 
					 | 
				
			||||||
        if self.model:
 | 
					 | 
				
			||||||
            return super().get_queryset(**kwargs).filter(public = True)
 | 
					 | 
				
			||||||
        return []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_object (self, **kwargs):
 | 
					 | 
				
			||||||
        if self.model:
 | 
					 | 
				
			||||||
            object = super().get_object(**kwargs)
 | 
					 | 
				
			||||||
            if object.public:
 | 
					 | 
				
			||||||
                return object
 | 
					 | 
				
			||||||
        return None
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_context_data (self, **kwargs):
 | 
					 | 
				
			||||||
        context = super().get_context_data(**kwargs)
 | 
					 | 
				
			||||||
        context.update({
 | 
					 | 
				
			||||||
            'sections': [
 | 
					 | 
				
			||||||
                section.get(self, self.request, object = self.object)
 | 
					 | 
				
			||||||
                    for section in self.sections
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
        return context
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Section (DetailView):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Base class for sections. Sections are view that can be used in detail view
 | 
					 | 
				
			||||||
    in order to have extra content about a post.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    model = None
 | 
					 | 
				
			||||||
    template_name = 'website/section.html'
 | 
					 | 
				
			||||||
    classes = ''
 | 
					 | 
				
			||||||
    title = ''
 | 
					 | 
				
			||||||
    header = ''
 | 
					 | 
				
			||||||
    bottom = ''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_context_data (self, **kwargs):
 | 
					 | 
				
			||||||
        context = super().get_context_date(**kwargs)
 | 
					 | 
				
			||||||
        context.update({
 | 
					 | 
				
			||||||
            'title': self.title,
 | 
					 | 
				
			||||||
            'header': self.header,
 | 
					 | 
				
			||||||
            'bottom': self.bottom,
 | 
					 | 
				
			||||||
            'classes': self.classes,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get (self, request, **kwargs):
 | 
					 | 
				
			||||||
        self.object = kwargs.get('object')
 | 
					 | 
				
			||||||
        context = self.get_context_data(**kwargs)
 | 
					 | 
				
			||||||
        return render_to_string(self.template_name, 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
 | 
					 | 
				
			||||||
    name = ''
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    list_view = PostListView
 | 
					 | 
				
			||||||
    list_routes = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detail_view = PostDetailView
 | 
					 | 
				
			||||||
    detail_sections = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__ (self):
 | 
					 | 
				
			||||||
        if not self.name:
 | 
					 | 
				
			||||||
            self.name = self.model._meta.verbose_name_plural
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.detail_sections = [
 | 
					 | 
				
			||||||
            section.as_view(model = self.model)
 | 
					 | 
				
			||||||
                for section in self.detail_sections
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
        self.detail_view = self.detail_view.as_view(
 | 
					 | 
				
			||||||
            model = self.model,
 | 
					 | 
				
			||||||
            sections = self.detail_sections
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        self.list_view = self.list_view.as_view(
 | 
					 | 
				
			||||||
            model = self.model
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.routes = [ route(self.model, self.list_view, base_name = self.name)
 | 
					 | 
				
			||||||
                            for route in self.list_routes ] + \
 | 
					 | 
				
			||||||
                      [ DetailRoute(self.model, self.detail_view,
 | 
					 | 
				
			||||||
                                    base_name = self.name) ]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user