forked from rc/aircox
		
	fix error with tags; add callable for related bindings; comments in PostListView; ...
This commit is contained in:
		@ -40,6 +40,10 @@ class MyModelPost(RelatedPost):
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: it is possible to assign a function as a bounded value; in such case, the
 | 
				
			||||||
 | 
					function will be called using arguments **(post, related_object)**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Routes
 | 
					## Routes
 | 
				
			||||||
Routes are used to generate the URLs of the website. We provide some of the
 | 
					Routes are used to generate the URLs of the website. We provide some of the
 | 
				
			||||||
common routes: for the detail view of course, but also to select all posts or
 | 
					common routes: for the detail view of course, but also to select all posts or
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,33 @@ from aircox.cms import routes
 | 
				
			|||||||
from aircox.cms import settings
 | 
					from aircox.cms import settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Comment(models.Model):
 | 
					class Routable:
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get_with_thread(cl, thread = None, queryset = None,
 | 
				
			||||||
 | 
					                        thread_model = None, thread_id = None):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Return posts of the cl's type that are children of the given thread.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        if not queryset:
 | 
				
			||||||
 | 
					            queryset = cl.objects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if thread:
 | 
				
			||||||
 | 
					            thread_model = type(thread)
 | 
				
			||||||
 | 
					            thread_id = thread.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        thread_model = ContentType.objects.get_for_model(thread_model)
 | 
				
			||||||
 | 
					        return queryset.filter(
 | 
				
			||||||
 | 
					            thread_id = thread_id,
 | 
				
			||||||
 | 
					            thread_type__pk = thread_model.id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def route_url(cl, route, kwargs = None):
 | 
				
			||||||
 | 
					        name = cl._website.name_of_model(cl)
 | 
				
			||||||
 | 
					        name = route.get_view_name(name)
 | 
				
			||||||
 | 
					        return reverse(name, kwargs = kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Comment(models.Model, Routable):
 | 
				
			||||||
    thread_type = models.ForeignKey(
 | 
					    thread_type = models.ForeignKey(
 | 
				
			||||||
        ContentType,
 | 
					        ContentType,
 | 
				
			||||||
        on_delete=models.SET_NULL,
 | 
					        on_delete=models.SET_NULL,
 | 
				
			||||||
@ -71,7 +97,7 @@ class Comment(models.Model):
 | 
				
			|||||||
        return super().save(*args, **kwargs)
 | 
					        return super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Post (models.Model):
 | 
					class Post (models.Model, Routable):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Base model that can be used as is if wanted. Represent a generic
 | 
					    Base model that can be used as is if wanted. Represent a generic
 | 
				
			||||||
    publication on the website.
 | 
					    publication on the website.
 | 
				
			||||||
@ -115,34 +141,15 @@ class Post (models.Model):
 | 
				
			|||||||
        default = '',
 | 
					        default = '',
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    image = models.ImageField(
 | 
					    image = models.ImageField(
 | 
				
			||||||
        blank = True, null = True
 | 
					        blank = True, null = True,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    tags = TaggableManager(
 | 
					    tags = TaggableManager(
 | 
				
			||||||
        _('tags'),
 | 
					        verbose_name = _('tags'),
 | 
				
			||||||
        blank = True,
 | 
					        blank = True,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    search_fields = [ 'title', 'content' ]
 | 
					    search_fields = [ 'title', 'content' ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def get_with_thread(cl, thread = None, queryset = None,
 | 
					 | 
				
			||||||
                        thread_model = None, thread_id = None):
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Return posts of the cl's type that are children of the given thread.
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        if not queryset:
 | 
					 | 
				
			||||||
            queryset = cl.objects
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if thread:
 | 
					 | 
				
			||||||
            thread_model = type(thread)
 | 
					 | 
				
			||||||
            thread_id = thread.id
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        thread_model = ContentType.objects.get_for_model(thread_model)
 | 
					 | 
				
			||||||
        return queryset.filter(
 | 
					 | 
				
			||||||
            thread_id = thread_id,
 | 
					 | 
				
			||||||
            thread_type__pk = thread_model.id
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_comments(self):
 | 
					    def get_comments(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Return comments pointing to this post
 | 
					        Return comments pointing to this post
 | 
				
			||||||
@ -166,12 +173,6 @@ class Post (models.Model):
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        return qs
 | 
					        return qs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def route_url(cl, route, kwargs = None):
 | 
					 | 
				
			||||||
        name = cl._website.name_of_model(cl)
 | 
					 | 
				
			||||||
        name = route.get_view_name(name)
 | 
					 | 
				
			||||||
        return reverse(name, kwargs = kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def make_safe(self):
 | 
					    def make_safe(self):
 | 
				
			||||||
        self.title = bleach.clean(
 | 
					        self.title = bleach.clean(
 | 
				
			||||||
            self.title,
 | 
					            self.title,
 | 
				
			||||||
@ -183,11 +184,18 @@ class Post (models.Model):
 | 
				
			|||||||
            tags=settings.AIRCOX_CMS_BLEACH_CONTENT_TAGS,
 | 
					            tags=settings.AIRCOX_CMS_BLEACH_CONTENT_TAGS,
 | 
				
			||||||
            attributes=settings.AIRCOX_CMS_BLEACH_CONTENT_ATTRS
 | 
					            attributes=settings.AIRCOX_CMS_BLEACH_CONTENT_ATTRS
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self.tags = [ bleach.clean(tag, tags=[]) for tag in self.tags.all() ]
 | 
					        if self.pk:
 | 
				
			||||||
 | 
					            self.tags.set(*[
 | 
				
			||||||
 | 
					                bleach.clean(tag, tags=[])
 | 
				
			||||||
 | 
					                for tag in self.tags.all()
 | 
				
			||||||
 | 
					            ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, make_safe = True, *args, **kwargs):
 | 
					    def save(self, make_safe = True, *args, **kwargs):
 | 
				
			||||||
        if make_safe:
 | 
					        if make_safe:
 | 
				
			||||||
            self.make_safe()
 | 
					            self.make_safe()
 | 
				
			||||||
 | 
					        if self.date and self.date.tzinfo is None or \
 | 
				
			||||||
 | 
					                self.date.tzinfo.utcoffset(self.date) is None:
 | 
				
			||||||
 | 
					            timezone.make_aware(self.date)
 | 
				
			||||||
        return super().save(*args, **kwargs)
 | 
					        return super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
@ -353,6 +361,9 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
				
			|||||||
            to update the post thread to the correct Post model (in order to
 | 
					            to update the post thread to the correct Post model (in order to
 | 
				
			||||||
            establish a parent-child relation between two models)
 | 
					            establish a parent-child relation between two models)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            When a callable is set as bound value, it will be called to retrieve
 | 
				
			||||||
 | 
					            the value, as: callable_func(post, related)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Note: bound values can be any value, not only Django field.
 | 
					            Note: bound values can be any value, not only Django field.
 | 
				
			||||||
        * post_to_rel: auto update related object when post is updated
 | 
					        * post_to_rel: auto update related object when post is updated
 | 
				
			||||||
        * rel_to_post: auto update the post when related object is updated
 | 
					        * rel_to_post: auto update the post when related object is updated
 | 
				
			||||||
@ -380,6 +391,8 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def get_rel_attr(self, attr):
 | 
					    def get_rel_attr(self, attr):
 | 
				
			||||||
        attr = self._relation.bindings.get(attr)
 | 
					        attr = self._relation.bindings.get(attr)
 | 
				
			||||||
 | 
					        if callable(attr):
 | 
				
			||||||
 | 
					            return attr(self, self.related)
 | 
				
			||||||
        return getattr(self.related, attr) if attr else None
 | 
					        return getattr(self.related, attr) if attr else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_rel_attr(self, attr, value):
 | 
					    def set_rel_attr(self, attr, value):
 | 
				
			||||||
@ -432,8 +445,8 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
				
			|||||||
        for attr, rel_attr in rel.bindings.items():
 | 
					        for attr, rel_attr in rel.bindings.items():
 | 
				
			||||||
            if attr == 'thread':
 | 
					            if attr == 'thread':
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            self.set_rel_attr
 | 
					            value = rel_attr(self, self.related) if callable(rel_attr) else \
 | 
				
			||||||
            value = getattr(self.related, rel_attr)
 | 
					                    getattr(self.related, rel_attr)
 | 
				
			||||||
            set_attr(attr, value)
 | 
					            set_attr(attr, value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if rel.thread_model:
 | 
					        if rel.thread_model:
 | 
				
			||||||
@ -453,14 +466,16 @@ class RelatedPost (Post, metaclass = RelatedPostBase):
 | 
				
			|||||||
        if self.pk and self._relation.rel_to_post:
 | 
					        if self.pk and self._relation.rel_to_post:
 | 
				
			||||||
            self.rel_to_post(False)
 | 
					            self.rel_to_post(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save (self, avoid_sync = False, *args, **kwargs):
 | 
					    def save (self, avoid_sync = False, save = True, *args, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        If avoid_relation, do not synchronise the post/related object.
 | 
					        * avoid_sync: do not synchronise the post/related object;
 | 
				
			||||||
 | 
					        * save: if False, does not call parent save functions
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        if not avoid_sync:
 | 
					        if not avoid_sync:
 | 
				
			||||||
            if not self.pk and self._relation.rel_to_post:
 | 
					            if not self.pk and self._relation.rel_to_post:
 | 
				
			||||||
                self.rel_to_post(False)
 | 
					                self.rel_to_post(False)
 | 
				
			||||||
            if self._relation.post_to_rel:
 | 
					            if self._relation.post_to_rel:
 | 
				
			||||||
                self.post_to_rel(True)
 | 
					                self.post_to_rel(True)
 | 
				
			||||||
        super().save(*args, **kwargs)
 | 
					        if save:
 | 
				
			||||||
 | 
					            super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -108,7 +108,6 @@ class ThreadRoute(Route):
 | 
				
			|||||||
        ('pk', '[0-9]+'),
 | 
					        ('pk', '[0-9]+'),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_thread(cl, model, thread_model, pk=None):
 | 
					    def get_thread(cl, model, thread_model, pk=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@ -183,3 +182,4 @@ class SearchRoute(Route):
 | 
				
			|||||||
            'search': request.GET.get('q') or '',
 | 
					            'search': request.GET.get('q') or '',
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,8 @@ class Section(View):
 | 
				
			|||||||
    to Section configuration/rendering. However, some data are considered
 | 
					    to Section configuration/rendering. However, some data are considered
 | 
				
			||||||
    as temporary, and are reset at each rendering, using given arguments.
 | 
					    as temporary, and are reset at each rendering, using given arguments.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    When get_context_data returns None, returns an empty string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ! Important Note: values given for rendering are considered as safe
 | 
					    ! Important Note: values given for rendering are considered as safe
 | 
				
			||||||
    HTML in templates.
 | 
					    HTML in templates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -90,6 +92,8 @@ class Section(View):
 | 
				
			|||||||
        self.kwargs = kwargs
 | 
					        self.kwargs = kwargs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context = self.get_context_data()
 | 
					        context = self.get_context_data()
 | 
				
			||||||
 | 
					        if not context:
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
        return render_to_string(self.template_name, context, request=request)
 | 
					        return render_to_string(self.template_name, context, request=request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -207,11 +211,15 @@ class List(Section):
 | 
				
			|||||||
        return self.object_list
 | 
					        return self.object_list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_context_data(self):
 | 
					    def get_context_data(self):
 | 
				
			||||||
 | 
					        object_list = self.object_list or self.get_object_list()
 | 
				
			||||||
 | 
					        if not object_list and not self.message_empty:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        context = super().get_context_data()
 | 
					        context = super().get_context_data()
 | 
				
			||||||
        context.update({
 | 
					        context.update({
 | 
				
			||||||
            'base_template': 'aircox/cms/section.html',
 | 
					            'base_template': 'aircox/cms/section.html',
 | 
				
			||||||
            'list': self,
 | 
					            'list': self,
 | 
				
			||||||
            'object_list': self.object_list or self.get_object_list(),
 | 
					            'object_list': object_list,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -223,9 +231,9 @@ class Comments(List):
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    title=_('Comments')
 | 
					    title=_('Comments')
 | 
				
			||||||
    css_class='comments'
 | 
					    css_class='comments'
 | 
				
			||||||
    paginate_by = 0
 | 
					 | 
				
			||||||
    truncate = 0
 | 
					    truncate = 0
 | 
				
			||||||
    fields = [ 'date', 'time', 'author', 'content' ]
 | 
					    fields = [ 'date', 'time', 'author', 'content' ]
 | 
				
			||||||
 | 
					    message_empty = _('no comment yet')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    comment_form = None
 | 
					    comment_form = None
 | 
				
			||||||
    success_message = ( _('Your message is awaiting for approval'),
 | 
					    success_message = ( _('Your message is awaiting for approval'),
 | 
				
			||||||
@ -240,6 +248,19 @@ class Comments(List):
 | 
				
			|||||||
                          attrs={ 'id': comment.id })
 | 
					                          attrs={ 'id': comment.id })
 | 
				
			||||||
                 for comment in qs ]
 | 
					                 for comment in qs ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property
 | 
				
			||||||
 | 
					    def url(self):
 | 
				
			||||||
 | 
					        import aircox.cms.models as models
 | 
				
			||||||
 | 
					        import aircox.cms.routes as routes
 | 
				
			||||||
 | 
					        if self.object:
 | 
				
			||||||
 | 
					            return models.Comment.route_url(routes.ThreadRoute, {
 | 
				
			||||||
 | 
					                'pk': self.object.id,
 | 
				
			||||||
 | 
					                'thread_model': self.object._website.name_of_model(
 | 
				
			||||||
 | 
					                    self.object.__class__
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        return ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_context_data(self):
 | 
					    def get_context_data(self):
 | 
				
			||||||
        post = self.object
 | 
					        post = self.object
 | 
				
			||||||
        if hasattr(post, 'allow_comments') and post.allow_comments:
 | 
					        if hasattr(post, 'allow_comments') and post.allow_comments:
 | 
				
			||||||
 | 
				
			|||||||
@ -6,25 +6,24 @@
 | 
				
			|||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block pre_title %}
 | 
					{% block pre_title %}
 | 
				
			||||||
<div class="pre_title metadata">
 | 
					<div class="pre_title meta">
 | 
				
			||||||
{% if object.thread %}
 | 
					    {% if object.thread %}
 | 
				
			||||||
<div class="threads">
 | 
					    <div class="threads">
 | 
				
			||||||
    {{ object|threads:' > '|safe }}
 | 
					        {{ object|threads:' > '|safe }}
 | 
				
			||||||
</div>
 | 
					    </div>
 | 
				
			||||||
{% endif %}
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<time datetime="{{ object.date }}">
 | 
					    <time datetime="{{ object.date }}">
 | 
				
			||||||
    {{ object.date|date:'l d F Y' }},
 | 
					        {{ object.date|date:'l d F Y' }},
 | 
				
			||||||
    {{ object.date|time:'H\hi' }}
 | 
					        {{ object.date|time:'H\hi' }}
 | 
				
			||||||
</time>
 | 
					    </time>
 | 
				
			||||||
 | 
					 | 
				
			||||||
{% if object.tags %}
 | 
					 | 
				
			||||||
{# TODO: url to the tags #}
 | 
					 | 
				
			||||||
<div class="tags">
 | 
					 | 
				
			||||||
    {{ object.tags.all|join:', ' }}
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
{% endif %}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if object.tags.all %}
 | 
				
			||||||
 | 
					    {# TODO: url to the tags #}
 | 
				
			||||||
 | 
					    <div class="tags">
 | 
				
			||||||
 | 
					        {{ object.tags.all|join:', ' }}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								cms/views.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								cms/views.py
									
									
									
									
									
								
							@ -44,20 +44,26 @@ class PostListView(PostBaseView, ListView):
 | 
				
			|||||||
    * embed: view is embedded, render only the list
 | 
					    * embed: view is embedded, render only the list
 | 
				
			||||||
    * exclude: exclude item of the given id
 | 
					    * exclude: exclude item of the given id
 | 
				
			||||||
    * order: 'desc' or 'asc'
 | 
					    * order: 'desc' or 'asc'
 | 
				
			||||||
    * fields: fields to render
 | 
					 | 
				
			||||||
    * page: page number
 | 
					    * page: page number
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    template_name = 'aircox/cms/list.html'
 | 
					    template_name = 'aircox/cms/list.html'
 | 
				
			||||||
    allow_empty = True
 | 
					    allow_empty = True
 | 
				
			||||||
    paginate_by = 25
 | 
					    paginate_by = 30
 | 
				
			||||||
    model = None
 | 
					    model = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    route = None
 | 
					    route = None
 | 
				
			||||||
    list = None
 | 
					    list = None
 | 
				
			||||||
 | 
					    css_class = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not self.list:
 | 
				
			||||||
 | 
					            self.list = sections.List(
 | 
				
			||||||
 | 
					                truncate = 32,
 | 
				
			||||||
 | 
					                fields = [ 'date', 'time', 'image', 'title', 'content' ],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def dispatch(self, request, *args, **kwargs):
 | 
					    def dispatch(self, request, *args, **kwargs):
 | 
				
			||||||
        self.route = self.kwargs.get('route') or self.route
 | 
					        self.route = self.kwargs.get('route') or self.route
 | 
				
			||||||
        return super().dispatch(request, *args, **kwargs)
 | 
					        return super().dispatch(request, *args, **kwargs)
 | 
				
			||||||
@ -104,15 +110,8 @@ class PostListView(PostBaseView, ListView):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        context['title'] = title
 | 
					        context['title'] = title
 | 
				
			||||||
        context['base_template'] = 'aircox/cms/website.html'
 | 
					        context['base_template'] = 'aircox/cms/website.html'
 | 
				
			||||||
        context['css_class'] = 'list'
 | 
					        context['css_class'] = 'list' if not self.css_class else \
 | 
				
			||||||
 | 
					                               'list ' + self.css_class
 | 
				
			||||||
        if not self.list:
 | 
					 | 
				
			||||||
            import aircox.cms.sections as sections
 | 
					 | 
				
			||||||
            self.list = sections.List(
 | 
					 | 
				
			||||||
                truncate = 32,
 | 
					 | 
				
			||||||
                fields = [ 'date', 'time', 'image', 'title', 'content' ],
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        context['list'] = self.list
 | 
					        context['list'] = self.list
 | 
				
			||||||
        # FIXME: list.url = if self.route: self.model(self.route, self.kwargs) else ''
 | 
					        # FIXME: list.url = if self.route: self.model(self.route, self.kwargs) else ''
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
				
			|||||||
@ -18,12 +18,13 @@ class Website:
 | 
				
			|||||||
    # user interaction
 | 
					    # user interaction
 | 
				
			||||||
    allow_comments = True
 | 
					    allow_comments = True
 | 
				
			||||||
    auto_publish_comments = False
 | 
					    auto_publish_comments = False
 | 
				
			||||||
 | 
					    comments_routes = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # components
 | 
					    # components
 | 
				
			||||||
    urls = []
 | 
					    urls = []
 | 
				
			||||||
    registry = {}
 | 
					    registry = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__ (self, menus = None, **kwargs):
 | 
					    def __init__(self, menus = None, **kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        * menus: a list of menus to add to the website
 | 
					        * menus: a list of menus to add to the website
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@ -36,13 +37,34 @@ class Website:
 | 
				
			|||||||
            for menu in menus:
 | 
					            for menu in menus:
 | 
				
			||||||
                self.set_menu(menu)
 | 
					                self.set_menu(menu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.comments_routes:
 | 
				
			||||||
 | 
					            self.register_comments_routes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def name_of_model (self, model):
 | 
					
 | 
				
			||||||
 | 
					    def name_of_model(self, model):
 | 
				
			||||||
        for name, _model in self.registry.items():
 | 
					        for name, _model in self.registry.items():
 | 
				
			||||||
            if model is _model:
 | 
					            if model is _model:
 | 
				
			||||||
                return name
 | 
					                return name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register_model (self, name, model):
 | 
					    def register_comments_routes(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Register routes for comments, for the moment, only:
 | 
				
			||||||
 | 
					        * ThreadRoute
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        import aircox.cms.models as models
 | 
				
			||||||
 | 
					        import aircox.cms.sections as sections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.register_list(
 | 
				
			||||||
 | 
					            'comment', models.Comment,
 | 
				
			||||||
 | 
					            routes = [routes.ThreadRoute],
 | 
				
			||||||
 | 
					            css_class = 'comments',
 | 
				
			||||||
 | 
					            list = sections.Comments(
 | 
				
			||||||
 | 
					                truncate = 30,
 | 
				
			||||||
 | 
					                fields = ['content','author','date','time'],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def register_model(self, name, model):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Register a model and return the name under which it is registered.
 | 
					        Register a model and return the name under which it is registered.
 | 
				
			||||||
        Raise a ValueError if another model is yet associated under this name.
 | 
					        Raise a ValueError if another model is yet associated under this name.
 | 
				
			||||||
@ -54,7 +76,7 @@ class Website:
 | 
				
			|||||||
        model._website = self
 | 
					        model._website = self
 | 
				
			||||||
        return name
 | 
					        return name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register_detail (self, name, model, view = views.PostDetailView,
 | 
					    def register_detail(self, name, model, view = views.PostDetailView,
 | 
				
			||||||
                         **view_kwargs):
 | 
					                         **view_kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Register a model and the detail view
 | 
					        Register a model and the detail view
 | 
				
			||||||
@ -68,7 +90,7 @@ class Website:
 | 
				
			|||||||
        self.urls.append(routes.DetailRoute.as_url(name, view))
 | 
					        self.urls.append(routes.DetailRoute.as_url(name, view))
 | 
				
			||||||
        self.registry[name] = model
 | 
					        self.registry[name] = model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register_list (self, name, model, view = views.PostListView,
 | 
					    def register_list(self, name, model, view = views.PostListView,
 | 
				
			||||||
                       routes = [], **view_kwargs):
 | 
					                       routes = [], **view_kwargs):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Register a model and the given list view using the given routes
 | 
					        Register a model and the given list view using the given routes
 | 
				
			||||||
@ -82,7 +104,7 @@ class Website:
 | 
				
			|||||||
        self.urls += [ route.as_url(name, view) for route in routes ]
 | 
					        self.urls += [ route.as_url(name, view) for route in routes ]
 | 
				
			||||||
        self.registry[name] = model
 | 
					        self.registry[name] = model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register (self, name, model, sections = None, routes = None,
 | 
					    def register(self, name, model, sections = None, routes = None,
 | 
				
			||||||
                  list_view = views.PostListView,
 | 
					                  list_view = views.PostListView,
 | 
				
			||||||
                  detail_view = views.PostDetailView,
 | 
					                  detail_view = views.PostDetailView,
 | 
				
			||||||
                  list_kwargs = {}, detail_kwargs = {}):
 | 
					                  list_kwargs = {}, detail_kwargs = {}):
 | 
				
			||||||
@ -104,7 +126,7 @@ class Website:
 | 
				
			|||||||
                **list_kwargs
 | 
					                **list_kwargs
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_menu (self, menu):
 | 
					    def set_menu(self, menu):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Set a menu, and remove any previous menu at the same position
 | 
					        Set a menu, and remove any previous menu at the same position
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
@ -114,7 +136,7 @@ class Website:
 | 
				
			|||||||
            menu.tag = 'side'
 | 
					            menu.tag = 'side'
 | 
				
			||||||
        self.menus[menu.position] = menu
 | 
					        self.menus[menu.position] = menu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_menu (self, position):
 | 
					    def get_menu(self, position):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Get an enabled menu by its position
 | 
					        Get an enabled menu by its position
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user