aircox-radiocampus/cms/website.py

188 lines
5.4 KiB
Python

from django.utils.text import slugify
from django.conf.urls import url
import aircox.cms.routes as routes
import aircox.cms.views as views
import aircox.cms.models as models
import aircox.cms.sections as sections
class Website:
"""
Describe a website and all its settings that are used for its rendering.
"""
## metadata
name = ''
domain = ''
description = 'An aircox website'
tags = 'aircox,radio,music'
## rendering
styles = ''
"""extra css style file"""
menus = None
"""dict of default menus used to render website pages"""
## user interaction
allow_comments = True
"""allow comments on the website"""
auto_publish_comments = False
"""publish comment without human approval"""
comments_routes = True
"""register list routes for the Comment model"""
## components
urls = []
"""list of urls generated thourgh registrations"""
registry = {}
"""dict of registered models by their name"""
def __init__(self, menus = None, **kwargs):
"""
* menus: a list of menus to add to the website
"""
self.registry = {}
self.urls = []
self.menus = {}
self.__dict__.update(kwargs)
if menus:
for menu in menus:
self.set_menu(menu)
if self.comments_routes:
self.register_comments_routes()
def name_of_model(self, model):
"""
Return the registered name for a given model if found.
"""
for name, _model in self.registry.items():
if model is _model:
return name
def register_comments_routes(self):
"""
Register routes for comments, for the moment, only
ThreadRoute
"""
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.
Raise a ValueError if another model is yet associated under this name.
"""
if name in self.registry:
if self.registry[name] is model:
return name
raise ValueError('A model has yet been registered under "{}"'
.format(name))
self.registry[name] = model
model._website = self
return name
def register_detail(self, name, model, view = views.PostDetailView,
**view_kwargs):
"""
Register a model and the detail view
"""
name = self.register_model(name, model)
if not view_kwargs.get('menus'):
view_kwargs['menus'] = self.menus
view = view.as_view(
website = self,
model = model,
**view_kwargs
)
self.urls.append(routes.DetailRoute.as_url(name, view))
self.registry[name] = model
def register_list(self, name, model, view = views.PostListView,
routes = [], **view_kwargs):
"""
Register a model and the given list view using the given routes
"""
name = self.register_model(name, model)
if not 'menus' in view_kwargs:
view_kwargs['menus'] = self.menus
view = view.as_view(
website = self,
model = model,
**view_kwargs
)
self.urls += [ route.as_url(name, view) for route in routes ]
self.registry[name] = model
def register_page(self, name, view = views.PageView, path = None,
**view_kwargs):
"""
Register a page that is accessible to the given path. If path is None,
use a slug of the name.
"""
if not 'menus' in view_kwargs:
view_kwargs['menus'] = self.menus
view = view.as_view(
website = self,
**view_kwargs
)
self.urls.append(url(
slugify(name) if path is None else path,
view = view,
name = name,
))
def register(self, name, model, sections = None, routes = None,
list_view = views.PostListView,
detail_view = views.PostDetailView,
list_kwargs = {}, detail_kwargs = {}):
"""
Register a detail and list view for a given model, using
routes. Just a wrapper around register_detail and
register_list.
"""
if sections:
self.register_detail(
name, model,
sections = sections,
**detail_kwargs
)
if routes:
self.register_list(
name, model,
routes = routes,
**list_kwargs
)
def set_menu(self, menu):
"""
Set a menu, and remove any previous menu at the same position
"""
if menu.position in ('footer','header'):
menu.tag = menu.position
elif menu.position in ('left', 'right'):
menu.tag = 'side'
self.menus[menu.position] = menu
def get_menu(self, position):
"""
Get an enabled menu by its position
"""
return self.menus.get(position)