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....

Thursday 15 August 2013

Python decorators.

Python Decorators:

What Can You Do With Decorators?

Decorators allow you to inject or modify code in functions or classes. Sounds a bit like Aspect-Oriented Programming (AOP) in Java, doesn't it? Except that it's both much simpler and (as a result) much more powerful. For example, suppose you'd like to do something at the entry and exit points of a function (such as perform some kind of security, tracing, locking, etc. -- all the standard arguments for AOP). With decorators, it looks like this:

@entryExit
def func1():
    print "inside func1()"

@entryExit
def func2():
    print "inside func2()"

The @ indicates the application of the decorator.
Function Decorators

A function decorator is applied to a function definition by placing it on the line before that function definition begins. For example:

@myDecorator
def aFunction():
    print "inside aFunction"

When the compiler passes over this code, aFunction() is compiled and the resulting function object is passed to the myDecorator code, which does something to produce a function-like object that is then substituted for the original aFunction().

What does the myDecorator code look like? Well, most introductory examples show this as a function, but I've found that it's easier to start understanding decorators by using classes as decoration mechanisms instead of functions. In addition, it's more powerful.

The only constraint upon the object returned by the decorator is that it can be used as a function -- which basically means it must be callable. Thus, any classes we use as decorators must implement __call__.

What should the decorator do? Well, it can do anything but usually you expect the original function code to be used at some point. This is not required, however:

class myDecorator(object):

    def __init__(self, f):
        print "inside myDecorator.__init__()"
        f() # Prove that function definition has completed

    def __call__(self):
        print "inside myDecorator.__call__()"

@myDecorator
def aFunction():
    print "inside aFunction()"

print "Finished decorating aFunction()"

aFunction()

When you run this code, you see:

inside myDecorator.__init__()
inside aFunction()
Finished decorating aFunction()
inside myDecorator.__call__()

Notice that the constructor for myDecorator is executed at the point of decoration of the function. Since we can call f() inside __init__(), it shows that the creation of f() is complete before the decorator is called. Note also that the decorator constructor receives the function object being decorated. Typically, you'll capture the function object in the constructor and later use it in the __call__() method (the fact that decoration and calling are two clear phases when using classes is why I argue that it's easier and more powerful this way).

When aFunction() is called after it has been decorated, we get completely different behavior; the myDecorator.__call__() method is called instead of the original code. That's because the act of decoration replaces the original function object with the result of the decoration -- in our case, the myDecorator object replaces aFunction. Indeed, before decorators were added you had to do something much less elegant to achieve the same thing:

def foo(): pass
foo = staticmethod(foo)

With the addition of the @ decoration operator, you now get the same result by saying:

@staticmethod
def foo(): pass

This is the reason why people argued against decorators, because the @ is just a little syntax sugar meaning "pass a function object through another function and assign the result to the original function."

The reason I think decorators will have such a big impact is because this little bit of syntax sugar changes the way you think about programming. Indeed, it brings the idea of "applying code to other code" (i.e.: macros) into mainstream thinking by formalizing it as a language construct.
Slightly More Useful

Now let's go back and implement the first example. Here, we'll do the more typical thing and actually use the code in the decorated functions:

class entryExit(object):

    def __init__(self, f):
        self.f = f

    def __call__(self):
        print "Entering", self.f.__name__
        self.f()
        print "Exited", self.f.__name__

@entryExit
def func1():
    print "inside func1()"

@entryExit
def func2():
    print "inside func2()"

func1()
func2()

The output is:

Entering func1
inside func1()
Exited func1
Entering func2
inside func2()
Exited func2

You can see that the decorated functions now have the "Entering" and "Exited" trace statements around the call.

The constructor stores the argument, which is the function object. In the call, we use the __name__ attribute of the function to display that function's name, then call the function itself.
Using Functions as Decorators

The only constraint on the result of a decorator is that it be callable, so it can properly replace the decorated function. In the above examples, I've replaced the original function with an object of a class that has a __call__() method. But a function object is also callable, so we can rewrite the previous example using a function instead of a class, like this:

def entryExit(f):
    def new_f():
        print "Entering", f.__name__
        f()
        print "Exited", f.__name__
    return new_f

@entryExit
def func1():
    print "inside func1()"

@entryExit
def func2():
    print "inside func2()"

func1()
func2()
print func1.__name__

new_f() is defined within the body of entryExit(), so it is created and returned when entryExit() is called. Note that new_f() is a closure, because it captures the actual value of f.

Once new_f() has been defined, it is returned from entryExit() so that the decorator mechanism can assign the result as the decorated function.

The output of the line print func1.__name__ is new_f, because the new_f function has been substituted for the original function during decoration. If this is a problem you can change the name of the decorator function before you return it:

def entryExit(f):
    def new_f():
        print "Entering", f.__name__
        f()
        print "Exited", f.__name__
    new_f.__name__ = f.__name__
    return new_f

The information you can dynamically get about functions, and the modifications you can make to those functions, are quite powerful in Python.


I would prefer to go through this document, here very good explanation given with lower level information.

http://pythonconquerstheuniverse.wordpress.com/2009/08/06/introduction-to-python-decorators-part-1/