[Cubicweb] Integrating CubicWeb views into Pyramid (long)
Christophe de Vienne
christophe at unlish.com
Wed Aug 6 00:51:48 CEST 2014
Le 05/08/2014 10:20, Florent Cayré a écrit :
> Hi Christophe,
> thanks for sharing your thoughts and pushing that hard towards a good
> Pyramid/CubicWeb integration.
My pleasure (so far :-p)
> Le 04/08/2014 20:59, Christophe de Vienne a écrit :
>> Registering a View
>> When we register a view in Pyramid, we pass various parameters to the
>> "add_view" function (or view_config decorator).
>> Three of them are the informations used for the first phase of the view
>> selection (later I call them the main predicates triplet):
>> - context
> What kind of information does this context hold? From what follows in
> you email,
> I understand it does not hold what you call "runtime" information like
> the user
> that performs the request and the web-session data. Is this "context"
> known at view "registration time" (as opposed to "web-request time")?
The context is built in the first phase of the request handling, by the
In the case of CubicWeb, it will be ResultSet.
>> - name
>> - request_type
>> Other parameters are predicates, like `accept`, `xhr` etc. These are
>> in a second phase, once the view(s) matching the first three are found.
> These are thus evaluated at web-request time, correct? Why not use
> these to
> evaluate the CW predicates? More on this later.
> Maybe we should split CW predicates into two categories in the long
> term: some may
> be more as a context (and evaluated and registration time if my
> understanding is
> correct). This could be a performance improvement, but nothing
> required in a first
I don't see a case were a predicate could be evaluated at registration time.
There are some interesting things to study to speedup the predicate
evaluation though, but imo not this one.
>> Use a custom IMultiView
>> Implements a IMultiView (see pyramid.config.views.MultiView) that
>> lookups in
>> the CW registry in hits __discriminator__.
>> One instance of this class would be registered for each __regid__,
>> like with
>> the ViewMapper-based solution.
>> * Not too difficult to implement
>> * Respect more the pyramid API: the lookup is performed at a
>> moment it is
>> expected by pyramid. In the end, pyramid will know the right
>> view, and
>> any other system looking up for a view will find an actual
>> one, not a
>> pseudo one.
>> * The CW views are not registered directly in pyramid
>> * Still doing two lookups in two different registries.
> IMHO, this is a first step we could make because:
> * removing CW registries is not the goal you just mentioned, which
> seems more
> important to me in the short term
> * the second cons you mention is not that bad: in this scenario, the
> registry is more like a one-element list per __regid__, which should
> not be a
> hard performance penalty
> * it really looks like a natural and simple approach, not a hack: not
> to understand, easy to debug... ok for me, at least as a first step
I do think it is a good first step, as it fulfill the goal and would be
compatible, api-wise, with more elaborate solutions.
>> Use CW predicates in add_view (basic)
>> Here we add a "cwselect" predicate to pyramid, that makes it able to
>> the cubicweb predicates.
>> * We by-pass the CW registry
>> * We loose the cw predicate weigths
> I am -1 because of this last point.
And your are most probably right, but it is still interesting to give
access to the cw predicates to the pyramid developers. So we should do
it, even if not the solution to our problem.
>> Use CW predicates in add_view + total ordering
>> Here we choose to drop the runtime evaluation of the predicates weight.
>> Instead, we evaluate the weight of a predicate when it matches, and
>> use that to
>> sort the views in the registry.
> I do not understand this: is the predicate weight evaluated or not? If
> yes, when?
The weight is evaluated once and for all at registration.
At runtime, only the match/not match part of it is interesting.
>> This would need either a slight change of the pyramid MultiView,
>> which would
>> sort the views in this new order we compute instead of the default
>> one, or a
>> change in the 'make' function so that the order of the view includes the
>> To use this system, we would need to duplicate the view registering
>> when the
>> expression has some "or" operators in it. The idea is to obtain
>> predicate expressions for add_view.
>> The only blocking point against that would be if some actual cw
>> returns a variable weight depending on the context, because it would
>> make it
>> impossible to pre-evaluate an expression weight if it matches.
> This depends on what the context is (see my first question about what
> the context
> holds): the logged-in user (known at web-request time) for example, is
> often used
> to compute a predicate weight (match_user_groups
> and so the web query parameters
> (in match_form_kwargs
> for example, but there is a complete list in the CW doc).
Ok. Is this context-related weight variation actually used to choose
between several views in a real-life application ?
I personally fail to imagine a case were belonging to 2 groups instead
of one would make a difference.
>> * By-pass the CW registry
>> * Very integrated solution
>> * We force the predicates to have a fixed value when they match.
> I do not understand this, but the impression I got reading your email
> is that the
> Pyramid registry ordering thing is too static to be used as a
> selection mecanism.
> However you mentioned a second predicate evaluation step at the
> beginning of you
> email, that should fulfill CW needs unless I misunderstood all this.
The registry ordering is used at the second step, for all remaining
The first step only match on a request type, a context type and a view name.
I have the impression that in most (if not all) cases, the views (and I
am talking only about the views) could be ordered even before any actual
evaluation of the predicates.
For example, let's consider the two expressions :
__select__ = is_instance('Event')
__select__ = is_instance('Event') & match_user_groups('managers')
If the first one matches, its weight would be 1.0
It the second one matches, its weight would be 2.0
Hence, the second one has a higher priority. If it matches, we don't
need to evaluate the first one -> it would have a lesser weight whether
it matches or not.
This only works if 1) we have no 'or' 2) the predicates have a fixed
weight once in the expression.
For point 1), the solution is to split the expression and register the
view twice (or more). For example :
__select__ = is_instance("Event") & match_user_groups('managers') |
is_instance("SmallEvent") & match_user_groups("users")
A view with such a select would be registered twice, with different
is_instance("Event") & match_user_groups('managers')
is_instance("SmallEvent") & match_user_groups("users")
For point 2), I am not aware of examples were the weight variation is
actually important in the selection process.
This approach reduce a little the possibilities of the selection system,
but makes it probably faster in many cases, and maybe easier to optimize
since the boolean arithmetics replaces the current complex one.
>> Use CW predicates in add_view + cw predicate weight
>> Add runtine evalution of predicate weigths into pyramid.
> This looks like a nice second step to me, but I am still unsure what
> the benefits
> would be: drop CW registries completely? If you think that Pyramid
> registries do
> not fit (which I am still unsure, see my previous question), we will
> more end-up
> with a re-implementation of CW registry features in Pyramid, which may
> (or not)
> be interesting for the Pyramid community. Paul probably has a good
> idea of the
It is indeed not a first intention solution.
But sooner or later we will wonder if it make sens to merge the CW
registry in the Pyramid one.
It may not, but it may too. :)
I hope I made it clearer
More information about the Cubicweb