forked from rc/aircox
		
	documentation
This commit is contained in:
		
							
								
								
									
										81
									
								
								cms/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								cms/README.md
									
									
									
									
									
										Normal file
									
								
							@ -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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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):
 | 
			
		||||
 | 
			
		||||
@ -170,4 +170,5 @@ class SearchRoute (Route):
 | 
			
		||||
        qs.distinct()
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
## TODO: by tag
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user