[Cubicweb] Understanding _cw

Christophe de Vienne christophe at unlish.com
Fri May 16 10:50:33 CEST 2014


Le 15/05/2014 23:51, aurélien campéas a écrit :
>
>
>       class HelloView(View):
>           __regid__ 'hello'
>           __select__ = is_instance('IndexCard') & title('summary')
>
>           def render(self, cw, w, t, _, rset, *args, **kw):
>               with t.h1(_class=self.__regid__):
>                   w(_('Hello, World, says %s' % cw.appli.name
>     <http://cw.appli.name>))
>               if cw.cnx.is_anonymous:
>                   w(t.p('Register now and get a free cw !'))
>               cw.view('blogentry', rset)
>
>
>
> This make me want to try:
>
>   @view('hello', is_instance('IndexCard') & title('summary'))
>   def render(self, cw, w, t, _, rset, *args, *kw):
>       with t.h1(_class=self.__regid__):
>           w(_('Hello, World, says %s' % cw.appli.name
> <http://cw.appli.name>))
>       if cw.cnx.is_anonymous:
>           w(t.p('Register now and get a free cw !'))
>       cw.view('blogentry', rset)

1) I think I disagree on the arguments you pass
2) Sounds like this make you want to try pyramid...

1) The arguments

I prefer when we pass what is strictly necessary only :
In the case of a single rendering function, what we need is :
- The data we render. This would be rset.
- The output stream w
- The tools we need to render : cnx or request (or, for views, something
between both which I have trouble to define and I will call
rendering_context), and cw.

Also :
- cnx should not be an attribute of cw, but the other way around.
- it 't' is a cwtags object to produce tags, I don't think it should be
here. An equivalent object accessible from 'w' could make sense.
- If we pass free functions as views, they do not need to become member
method (ie, no 'self' needed).
- the identity informations should be bound to the request, even if the
cnx has an identity.
- 'current' language is bound to the request, the view rendering
context, or cnx.

This would give :

For a free rendering function :

@view('hello', is_instance('IndexCard') & title('summary'))
def render(rendering_context, w, rset):
    _ = rendering_context.i18n._
    with w.h1(class_=rendering_context.view_regid):
        w(_(u"Hello World, says
{}".format(rendering_context.cw.appli.name)))
    if rendering_context.identity.is_anonymous:
        w.p(_(u"Register now and get a free cw:"))
    rendering_context.view('blogentry', rset)

For a class view:

@view('hello', is_instance('IndexCard') & title('summary'))
class Hello(object):
    def __init__(self, rendering_context, w, rset):
        self.ctx = rendering_context
        self.w = w
        self.rset = rset
        self._ = self.ctx.i18n._

    def __call__(self):
        w, u = self.w, self._
        with w.h1(class_=self.ctx.view_regid):
            w(_(u"Hello World, says {}".format(self.ctx.cw.appli.name)))
        if self.ctx.identity.is_anonymous:
            w.p(_(u"Register now and get a free cw:"))
        self.ctx.view('blogentry', rset)


2) Pyramid-likeliness

What you almost suggest is that the regid and the selector don't belong
to the appobject itself but to its registration.
Putting it this way would make it more natural to switch from classes to
simple functions when it's enough.

In pyramid, the views (which strictly correspond to what cw controllers
are) can be functions or classes.
The selection predicates are not part of the view itself but are given
to the 'add_view' api, which register the view.
The views take, as arguments, a request object and an optional context
(in cw it is the rset).

When the view is a function, it is defined like this :

    def some_function(request, context):
        return response

When it is a class :

    class SomeClassView(object):
        def __init__(self, request, context):
            # ...

        def __call__(self):
            return response

The advantage of class views is that they facilitate the reuse of code
chunks from one class to another.

My point is that CW is very close to this pattern, except that :
- the parameters fed to the __call__ function (or its equivalent
'publish', 'render' etc) are often the same as the ones passed to the
constructor.
- the regid and the selectors are on the class itself


I think that pyramid is a good example of working patterns that are
close to CW, and should be at least a source of inspiration for
designing the future CW (if not a base by itself but that's another
challenge and I want to experiment first).


My few iconoclasts cents :-)

Christophe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cubicweb.org/pipermail/cubicweb/attachments/20140516/0796feae/attachment-0095.html>


More information about the Cubicweb mailing list