Clarification on variables in views

57 views
Skip to first unread message

shapova...@gmail.com

unread,
Jul 7, 2013, 10:48:41 AM7/7/13
to web...@googlegroups.com
Hi!


So, what is recommended way of checking if var is defined and passed to a view? 
i.e. avoiding errors
<type 'exceptions.NameError'> name 'foo' is not defined

I see at least 3 ways, one is using 'try ... except' in a view:

{{block content_block}}
{{try:}}
{{=message or ""}}
{{except:}} <h1>Message not defined!</h1>
{{pass}}
{{end}}

other, using "if":
{{block content_block}}
{{if 'message' in globals():}}
{{=message or ""}}
{{pass}}
{{end}}

and also we can use globals().get():
{{=globals().get('message', False)}}
which will return False if message was not returned with dict in controller.

Something like this is used in default layout along with "or" that simply checks if var is not empty.

And what if I have a lot of variables to return from controller?
Then returning locals seems to be simpler and cleaner way (at least in terms of syntax), but on the other hand I really like the idea of passing only selected variables (that will be used) to the view, not all I have in controller. 
Probably somebody can point out to other security issues with returning locals to all views?

villas

unread,
Jul 7, 2013, 4:59:39 PM7/7/13
to
It seems that you already know how to check whether variables exist,  so you have already answered the question.

However,  I think the entire premise of the question seems strange.  If you are the developer you should know what variables you are going to be using in the view?  So, just make sure they always exist so you don't have to mess up your view with all those tests.

Maybe if you doing something unusal it is better to state the use case?

There is no harm in passing all the variables to your view,  as long as you are only exposing the ones that you wish to expose.  Generic views can expose all the variables and that is insecure,  so generic views are turned off by default for production.  As long as you create your own custom views then you can pass whatever variables you wish.

shapova...@gmail.com

unread,
Jul 7, 2013, 5:21:40 PM7/7/13
to
thanks for reply.

Yes, I've showed 3 ways of checking if var was previously defined, but the question was about preferred way of doing that in Web2Py, also I want to add 'not empty' to this check.


> If you are the developer you should know what variables you are going to be using in the view?

It may happen that views are written by other people, etc, isn't it better to introduce as much independence as possible?

Here is my case, but I guess there may be other similar. 

I keep content for my static pages in db. It is broken in parts like footer_block, header_block, content_block, etc. 
And I use blocks in views, so I can fill parts of view with content from db, or leave them with default content from extended view (i.e. my version of layout.html) with {{super}}. Also, some part of page can be empty in db. 

So, I thought that it would be a good idea to return only non-empty parts to the view, and in case when some part is empty in db, it will not be passed to the view, and content from extended layout will be used.

This is in the view that extends main template, this only checks if var is defined, but not if it is not empty.
{{block header_block}} {{try:}} {{=header_block or ''}} {{except:}} {{super}} {{pass}} {{end}}

Does it make sense?

shapova...@gmail.com

unread,
Jul 7, 2013, 5:27:16 PM7/7/13
to web...@googlegroups.com
> There is no harm in passing all the variables to your view,  as long as you are only exposing the ones that you wish to expose.  

and by exposing vars you mean using them like {{=message}}, or?

villas

unread,
Jul 7, 2013, 5:50:01 PM7/7/13
to web...@googlegroups.com
It seems like you are doing some complex things with the views.  That is fine,  but personally I find this:

1. In MVC it is more recommended to collect and prepare all your data in the controller and then pass all that to the view when it is ready.
2. In that way you can make sure that all the variables exist.
3. If someone else is writing a view,  you can still inform them all the variables which are available. You might develop your own conventions for that.

If your method of working does not allow that workflow,  you can still do what you are doing,  but I don't think there is a 'recommended' way.  The methods of checking whether variables exist is really a python question and not one specific to web2py.  You already know some methods to do that.

By 'exposing' the variables,  yes,  I meant for example {{=myvar}}.  I mean you can pass locals() to the view,  but you do not need to expose them all to the public.

shapova...@gmail.com

unread,
Jul 7, 2013, 6:05:13 PM7/7/13
to
villas, I agree with you on 1-3. Probably I over-complicated the workflow at some point.

Still, what approach do you think of, when some parts (vars) returned from controller (and db) have empty values and then we need to keep extended's layout values in that places (i.e. {{super}})?

Processing web page templates doesn't always mean substituting all the placeholders with variables from db, sometimes it needs to be adaptive to the data, right? 

Anthony

unread,
Jul 7, 2013, 8:46:59 PM7/7/13
to web...@googlegroups.com
Still, what approach do you think of, when some parts (vars) returned from controller (and db) have empty values and then we need to keep extended's layout values in that places (i.e. {{super}})?

The other approach would be to return a value of None (or other "falsey" value) for the variable in question rather than excluding the value altogether. You'll still need a conditional in the view, but you won't have to check whether the variable exists at all.

Anthony

villas

unread,
Jul 8, 2013, 7:24:45 AM7/8/13
to web...@googlegroups.com
As Anthony says,  initialize all your varibles using a 'falsey' value,  e.g.

def myfunction():
    myvar1 = ''
    myvar2 = ''
    if conditon1:
        myvar1 = get_data_from_db()
    if conditon2:
        myvar2 = get_data_from_somewhere_else()
    return dict(myvar1=myvar1, myvar2=myvar2)

In that way you will always have all the variables available.  If blank, they print as empty strings.  You can always test for none-empty values with {{if myvar1:}}  etc.


Reply all
Reply to author
Forward
0 new messages