From 54910f4df9a3c097034115385d7bad3d3600cbb7 Mon Sep 17 00:00:00 2001 From: bkfox Date: Thu, 19 May 2016 16:45:13 +0200 Subject: [PATCH] documentation --- cms/README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++ cms/models.py | 39 +++++++++++++++++----- cms/routes.py | 1 + cms/website.py | 5 +++ liquidsoap/views.py | 1 - programs/models.py | 2 +- 6 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 cms/README.md diff --git a/cms/README.md b/cms/README.md new file mode 100644 index 0000000..e1b87ae --- /dev/null +++ b/cms/README.md @@ -0,0 +1,81 @@ +# Aircox.CMS +Simple CMS generator used in Aircox. Main features includes: +- website configuration and templating +- articles and static pages +- sections: embeddable views used to display related elements of an object +- posts related to external models: + - attributes binding, automatically updated + - personalization of view rendering, using templates or sections + - integrated admin interface if desired +- list and detail views + routing +- positioned menus using views +- comment + +We aims here to automatize most common tasks and to ease website +configuration. + +# Architecture +A **Website** holds all required informations to run the server instance. It +is used to register all kind of posts, routes to the views, menus, etc. + +Basically, for each type of publication, the user declare the corresponding +model, the routes, the sections used for rendering, and register them using +website.register. + +## Posts +**Post** is the base model for a publication. **Article** is the provided model +for articles and static pages. + +**RelatedPost** is used to generate posts related to a model, the corresponding +bindings and so on. The idea is that you declare your own models using it as +parent, and give informations for bindings and so on. This is as simple as: + +```python +class MyModelPost(RelatedPost): + class Relation: + model = MyModel + mapping = { + 'thread': 'parent_field_name', + 'title': 'name' + } +``` + +## Routes +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 +by thread, date, search, tags. + +It is of course possible to create your own routes. + +Routes are registered to a router (FIXME: it might be possible that we remove +this later) + + +## Section +Sections are used to render part of a publication, for example to render a +playlist related to the diffusion of a program. + +If the rendering of a publication can vary depending the related element, in +most of the cases when we render elements, we can find the same patterns: a +picture, a text, a list of URLs/related posts/other items. + +In order to avoid to much code writing and the multiplication of template +files (e.g. one for each type of publication), we prefer to declare these +sections and configure them. This reduce the work, keep design coherent, +and reduce the risk of bugs and so on. + + +## Website +This class is used to create the website itself and regroup all the needed +informations to make it beautiful. There are different steps to create the +website, using instance of the Website class: + +1. Create the Website instance with all basic information: name, tags, + description, menus and so on. +2. For each type of publication, register it using a Post model, a list of + used sections, routes, and optional parameters. The given name is used + for routing. +3. Register website's URLs to Django. +4. Change templates and css styles if needed. + + diff --git a/cms/models.py b/cms/models.py index 7f7ed26..bb4cd29 100644 --- a/cms/models.py +++ b/cms/models.py @@ -14,6 +14,10 @@ from taggit.managers import TaggableManager class Post (models.Model): + """ + Base model that can be used as is if wanted. Represent a generic + publication on the website. + """ thread_type = models.ForeignKey( ContentType, on_delete=models.SET_NULL, @@ -64,6 +68,9 @@ class Post (models.Model): class Article (Post): + """ + Represent an article or a static page on the website. + """ static_page = models.BooleanField( _('static page'), default = False, @@ -141,12 +148,28 @@ class RelatedPostBase (models.base.ModelBase): class RelatedPost (Post, metaclass = RelatedPostBase): """ - Use this post to generate Posts that are related to an external model. An - extra field "related" will be generated, and some bindings are possible to - update te related object on save if desired; + Post linked to an object of other model. This object is accessible through + the field "related". - This is done through a class name Relation inside the declaration of the new - model. + It is possible to map attributes of the Post to the ones of the Related + Object. It is also possible to automatically update post's thread based + on the Related Object's parent if it is required. + + Mapping can ensure that the Related Object will be updated when mapped + fields of the Post are updated. + + To configure the Related Post, you just need to create set attributes of + the Relation sub-class. + + ``` + class MyModelPost(RelatedPost): + class Relation: + model = MyModel + mapping = { + 'thread': 'parent_field_name', + 'title': 'name' + } + ``` """ related = None @@ -165,13 +188,11 @@ class RelatedPost (Post, metaclass = RelatedPostBase): If there is a post_attr "thread", the corresponding rel_attr is used to update the post thread to the correct Post model (in order to establish a parent-child relation between two models) - * thread_model: generated by the metaclass that point to the - RelatedModel class related to the model that is the parent of - the current related one. + * thread_model: generated by the metaclass, points to the RelatedPost + model generated for the mapping.thread object. """ model = None mapping = None # values to map { post_attr: rel_attr } - thread = None thread_model = None def get_attribute (self, attr): diff --git a/cms/routes.py b/cms/routes.py index 521035d..700c090 100644 --- a/cms/routes.py +++ b/cms/routes.py @@ -170,4 +170,5 @@ class SearchRoute (Route): qs.distinct() return qs +## TODO: by tag diff --git a/cms/website.py b/cms/website.py index 0b693a2..a9de41b 100644 --- a/cms/website.py +++ b/cms/website.py @@ -67,6 +67,11 @@ class Website: def register (self, name, model, sections = None, routes = None, 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, diff --git a/liquidsoap/views.py b/liquidsoap/views.py index ba14f53..9abce54 100644 --- a/liquidsoap/views.py +++ b/liquidsoap/views.py @@ -36,7 +36,6 @@ class Actions: def skip (cl, monitor, controller, source): source.skip() - class LiquidControl (View): template_name = 'aircox/liquidsoap/controller.html' diff --git a/programs/models.py b/programs/models.py index 2520944..663c51f 100755 --- a/programs/models.py +++ b/programs/models.py @@ -744,7 +744,7 @@ class Log (models.Model): logger.info('log #%s: %s%s', str(self), self.comment or '', - '\n - {}: #{}'.format(self.related_type, self.related_id) + ' -- {} #{}'.format(self.related_type, self.related_id) if self.related_object else '' )