Friday, 16 August 2013

OpenERP CMS

Hello everyone,

Here I am with CMS implementation in OpenERP.

Before we start CMS design introduction lets have look at decorators in python as it is widely used here.

For decorators you can either go through Python standard documentation of go through my following blog which describes it briefly.

http://mishekha.blogspot.in/2013/08/python-decorators.html

CMS, content management system, a system where your content is managed which allows publishing, editing of content, a biggest example is bloggers where you put your content, edit it and publish it, same here OpenERP CMS allows website implementation stuff inside OpenERP itself.

So lets start with CMS:
OpenERP have developed a website module, this module has website controller(main.py website module)  inheriting Home controller(main.py web module) and overriding index method of it which is called while requesting OpenERP with / path(root path, just go through main.py -> Home class, index method check the route, you will find path as '/' so it means '/' path request controller is index method), here what we did if someone enters just / path then we opened website view and if someone enters /admin then we opened regular OpenERP instance, as I described(with content of other site documentation) decorator used here, so @http.route('/') is called at the time of entry and exit of function and current function is passed as a argument to route method of http module.

We have page method in website class which renders page with reference of page path given, path given will nothing but the page name, like here given website.homepage in root path we redirected to website.homepage page, first we get the rendering context by calling get_rendering_context method(Described below), and then renders path i.e. website.homepage page by calling render method of ir.ui.view go through render method of ir.ui.view in which we used and also go through qweb.py in server tools.py where all logic resides to render qweb template by parsing qweb template, the ultimate result of this method will be html, as it is going to be return response of request and going to be populated in browser and browser understands html.

get_rendering_context:
--------------------------------------
While defining template you will have needs of dynamic values from some object like res.company, say for example we have template where I have set title = <title><t t-esc="title or res_company.name"/></title>, so here the value of title come as res.company name, so we will have get_rendering_context method in our website model(your cms module's model) which will set the context with res.company browse record for current user so that while rendering template we can have data from context, to check go to website controller(main.py) and check page method there.



Defined template are stored a qweb template, you have to give modulename.pagename(template name), it is going to be partitioned by .(dot), and the first part going to set as module and second part as view name and it is found by get_object_reference of ir.model.data which returns id and model(id of view in ir.model.data and model i.e. ir.ui.view) and then we call read_combined method this method reads the view and its inherit view that's why its name is read_combined, the view returned here will be the qweb template and which converted into html by render method of qweb.py in tools, qweb module has QwebXML class which has method render which parsis the view and convert it into html.

One can go through cms example of HR, CRM, Event, Mail, Sale. All have different controller path, so to develop a new cms module you need to follow following things:

Directory structure:
website_modulename
        |
        -> controllers
        |        |
        |        -> __init__.py
        |           main.py
        |
        -> static
             |
             -> src
                 |
                 -> css -> your css file where your styles for your       
                                view/elements  resides.
                 |
                 -> js -> your js file
                 |
                 -> xml ->
        |
        -> views
            |
            -> your_module_view.xml -> these are the views which are going to be
                stroed as a qweb views which is loaded by path name
               like for example /event/page/contactus(render method of qweb do the
               job to fetch the view from database and render it)
        |
        -> modulename.py -> your model defination file where you define your
             model for your website
        |
        -> __init__.py
        |
        -> __openerp__.py -> Module manifest file.


Now write a model in the way you needs if you need any extra fields in website to some model like you can see here as a example we added a field "website_published" on model mail.mesage in website_mail module, also write the view for your website for example, for your pages for example Home page, Contact US, About US menus etc as a qweb template(fore reference you can take an example of website module website_view.xml), set a unique name to template.
After doing this much develop a controller in main.py say for example:

clas myModule(http.Controller):
    @http.route('/myModule/page/home', type='http', auth="public")
    def myFunction(self, bla, bla):
        //your logic
        //get_rendering_context
        //render your view by passing view name in calling website.render('viewName', context_values)

Explanation on above signature:
-------------------------------------------------------
path shows when request comes with this path given function is going to call(as all this path are loaded/registered when server is started), then type parameters shows which kind of request it will be, http or json, when you enter this path in URL like localhost:8069/myModule/page/home it will be an HTTP request(for further reference you can read http and json difference, but the basic difference is http sends data in either chunks, deflate, gzip, data is sent in a series of "chunks"(if chunks transfer-encoding used) while JSON(JavaScript Object Notation) as the name suggest it is transfers data in JavaScript like object {key: value} which so light weighted so future web applications are developed and uses JSON format for their request and response data format)
auth: auth can have one of three value 1. user, 2. admin, 3. none
``user``: The user must be authenticated and the current request will perform using the rights of the user.
``admin``: The user may not be authenticated and the current request will perform using the admin user.
``none``: The method is always active, even if there is no database. Mainly used by the framework and
        authentication modules. There request code will not have any facilities to access the database nor have any
        configuration indicating the current database nor the current user.

And and and website module adds one more kind of authentication that is 'public' so that method can be accessible publicly so to access all database related stuff public uid used.


Now where you need js and css ?
you can write styles for your template elements and if you need something special like controll over elements and view and client side events etc then you controll it by js like, one of the element of my template has input element and I want that when I change that element value I need to reflect it in other element like do a total etc(onchange), there are lots of task which are accomplished by client side itseelf there is no need of server trip so we will do it using js.

That's it, (Note: Still CMS evolving and there may be large changes in future but this post describes basic design of CMS as of now.)


Feel to raise your query, your feedback are always welcome....