Conditional issue

2 views
Skip to first unread message

Martin

unread,
Nov 6, 2007, 11:47:37 AM11/6/07
to brevé template engine, li...@martinpp.co.uk

Hi there,

I am now extensively using Breve as my templating system of choice.
Recently I have been adding in some user login functionality and am
seeking advice on the following:

How to deal with conditional cases involving objects in templates?

Consider the following in a template:
when ('user' in controller.session)
[
controller.session['user'].preferences
]

Where session is a dictionary and user is either a User instance or
None.
Now, because the expression is evaluated fully the template will
generate the error:
AttributeError: 'NoneType' object has no attribute 'preferences' when
User is None.

The solution I am considering is:
* A silent accessor wrapper - e.g.
controller.get('session.user.preferences') that just fails silently on
error

But can anyone suggest a better/cleaner solution?


ta,


Martin

Cliff Wells

unread,
Nov 6, 2007, 7:41:28 PM11/6/07
to breve-...@googlegroups.com, li...@martinpp.co.uk
On Tue, 2007-11-06 at 08:47 -0800, Martin wrote:

> Consider the following in a template:
> when ('user' in controller.session)
> [
> controller.session['user'].preferences
> ]
>
> Where session is a dictionary and user is either a User instance or
> None.
> Now, because the expression is evaluated fully the template will
> generate the error:
> AttributeError: 'NoneType' object has no attribute 'preferences' when
> User is None.

What I'd *like* to do (but haven't figured out yet) is somehow implement
lazy evaluation for the conditionals in Breve. Another feature that
would help in this case would be a functional equivalent to Python's
exception handling.

Meanwhile, my typical approach to this type of problem is to solve it in
the controller:

def user_preferences ( session ):
try:
return session [ 'user' ].preferences
except KeyError:
return None

register_global ( 'user_preferences', user_preferences )


Then you can simply use this function in your template:

preferences ( controller.session )


Another approach (ugly but I suppose it works in a pinch):

( 'user' in controller.session and controller.session [ 'user' ].preferences ) or None


Regards,
Cliff


cbrain

unread,
Nov 8, 2007, 3:16:28 AM11/8/07
to brevé template engine
If you're using Python 2.5, you have the "a if b else c" construction
available, which works like "b ? a : c" in for example C (and in other
languages). So what you could do is something like:

html [
body [
(
controller.session['user'].preferences
)
if user in controller.session else
(
"You need to log in first!"
)
]
]

This does lazy evaluation as requested. But it only works in Python
2.5, which may be a problem for you.

With kind regards,
Sven


On Nov 6, 5:47 pm, Martin <martinpengellyphill...@googlemail.com>
wrote:

cbrain

unread,
Nov 8, 2007, 3:18:11 AM11/8/07
to brevé template engine
I see that I've forgotten the quotes around 'user' in the 'if' line,
but you get the picture, of course.

Sven

Martin

unread,
Nov 29, 2007, 7:39:37 AM11/29/07
to brevé template engine
Hi Sven,

Thank you for your suggestion. I am currently proposing that we move
to Python 2.5 so this could prove the final solution.
In the meantime I have implemented a simple safe accessor function on
the controller.

Martin

Cliff Wells

unread,
Feb 12, 2008, 2:32:16 PM2/12/08
to breve-...@googlegroups.com
This is massively belated but for some reason it only just now occurred
to me =) I've been toying with complex approaches (think proxy objects)
to emulate lazy evaluation when something stupidly simple was sitting
right in front of me (see below):

On Tue, 2007-11-06 at 08:47 -0800, Martin wrote:
>

The only place I'm aware of in Python 2.4 where lazy evaluation is
available are the "and" and "or" boolean operators. That being the
case, the above can be written as:

'user' in controller.session and (
controller.session['user'].preferences
)

This won't raise an exception as the parenthesized expression is never
evaluated if the condition isn't true.

Of course, in Python 2.5 I suggest using the ternary "if" operator.

Regards,
Cliff


Martin

unread,
Feb 20, 2008, 12:42:48 PM2/20/08
to brevé template engine
Thanks for the follow-up Cliff.

Martin

cbrain

unread,
Mar 26, 2008, 6:09:57 PM3/26/08
to brevé template engine
Hello Cliff,

Doesn't your example evaluate to False when 'user' is not in fact in
'controller.session'? And wouldn't Brevé actually display this as the
literal text 'False'?

With kind regards,
cbrain

Cliff Wells

unread,
Mar 26, 2008, 9:46:00 PM3/26/08
to breve-...@googlegroups.com
On Wed, 2008-03-26 at 15:09 -0700, cbrain wrote:
> Hello Cliff,
>
> Doesn't your example evaluate to False when 'user' is not in fact in
> 'controller.session'? And wouldn't Brevé actually display this as the
> literal text 'False'?

It does evaluate to False, but Breve renders it as an empty string.

Regards,
Cliff

Cliff Wells

unread,
Mar 27, 2008, 6:55:00 PM3/27/08
to breve-...@googlegroups.com

On Wed, 2008-03-26 at 15:09 -0700, cbrain wrote:
> Hello Cliff,
>
> Doesn't your example evaluate to False when 'user' is not in fact in
> 'controller.session'? And wouldn't Brevé actually display this as the
> literal text 'False'?

Actually, it appears you are correct. I was basing this idea off of my
usage under TurboGears and Pylons where it turns out the variable used
to determine if someone is logged in is either an empty string or a user
id of some sort, so it works well.

Perhaps I should add a boolean renderer to Breve to support this idea?

I'm not thinking having a boolean render as 'True' or 'False' is going
to be of real use (but perhaps my use-case is too small to say for
sure). Having False render as '' would be of definite utility, although
I'm not sure what True should render as (although in the example above
it wouldn't be rendered at all).

Thoughts?

Cliff

cbrain

unread,
Mar 28, 2008, 7:54:59 AM3/28/08
to brevé template engine
Hello Cliff,

I wouldn't mind False being rendered as ''. As for True, I have no
ideas on what that could be rendered as. Perhaps it would be best not
to render it at all and raise an exception instead?

Another option that does not require and changes to Brevé would be to
use:

'user' in controller.session and controller.session['user'] or
''

This renders the 'and' item if the expression is True and the 'or'
item if the expression is False.
With kind regards,
cbrain

Cliff Wells

unread,
Mar 28, 2008, 11:49:43 AM3/28/08
to breve-...@googlegroups.com

On Fri, 2008-03-28 at 04:54 -0700, cbrain wrote:
> Hello Cliff,
>
> I wouldn't mind False being rendered as ''. As for True, I have no
> ideas on what that could be rendered as. Perhaps it would be best not
> to render it at all and raise an exception instead?
>
> Another option that does not require and changes to Brevé would be to
> use:
>
> 'user' in controller.session and controller.session['user'] or
> ''
>
> This renders the 'and' item if the expression is True and the 'or'
> item if the expression is False.
> With kind regards,
> cbrain

Yet another option would be to simply have a test() function that
performed the equivalent:

def test ( v ):
return v or ''

then you could do

test ( value ) and (
div [ "It's true" ]
)

etc.

Cliff

Reply all
Reply to author
Forward
0 new messages