Parsing python from db fields?

161 views
Skip to first unread message

RKS

unread,
Jun 21, 2012, 2:27:48 PM6/21/12
to web...@googlegroups.com
I have a table defined with some old fashioned fields. When printing the fields in a view I use {{=XML(field.name)}} and so far this works great for all the HTML I've been putting in there all this time.

Now I've come to a situation where I'm trying to print some python from a field. Might be recursive, but if I have {{=field.name}} it prints that out directly instead of recognizing that it's a call and should go look for the field referenced. The reason I'm doing it this way is that my view is defined for all items of that type. One item has some differences and it should include another HTML file such as {{include "html.html"}} but that just prints instead of trying to find that html and include it.

Hopefully this wasn't so confusing.

So instead of {{=XML(field.name)}} when printing this particular field, what should this be in order to parse the python and html inside? Thanks.

Anthony

unread,
Jun 21, 2012, 4:12:31 PM6/21/12
to web...@googlegroups.com
Are you saying the content of field.name is actually Python code that you want to execute right there within the template? In that case, maybe you could use Python eval or exec inside the {{...}}.

Anthony

RKS

unread,
Jun 21, 2012, 5:42:52 PM6/21/12
to web...@googlegroups.com
Yes. Inside the actual field I use HTML and python. If I use {{=XML(blog.body)}} then I can insert all the HTML I want inside that field from the db administration. Very helpful.

But now I want to be able to insert {{=blog.title}} inside the blog.body field and when it renders int he view I want to execute {{=blog.title}}. Also, I have an HTML view that aggregates all of the blogs. So I want to include this inside the field blog.body.

So with your example are you saying when I use {{=XML(blog.body)}} I should use {{=eval(blog.body)}} or are you telling me to put eval or exec inside the {{=blog.title}} that I am calling inside the field? So would it be {{=exec(blog.body)}} or {{=exec(blog.title)}} inside blog.body?

Sorry, this all seems confusing. Thanks.

Anthony

unread,
Jun 21, 2012, 6:32:10 PM6/21/12
to web...@googlegroups.com
I see -- you want to be able to treat blog.body as a web2py template, not as HTML content or pure Python. Maybe try something like this:

{{from gluon.template import render}}
{{=XML(render(blog.body, context=response._vars))}}

Or maybe use context=globals() if the template needs to access other objects in the view environment besides the items returned by the controller (e.g., models or web2py API objects).

You could also do that in the controller and return the XML object from the controller.

Anthony

Or maybe try context=globals() if you need other items in the environment besides those returned by the controller.

RKS

unread,
Jun 21, 2012, 11:50:28 PM6/21/12
to web...@googlegroups.com
Hmm. I'm going to try and play with this a little tonight and report back tomorrow but on first try both these solutions return an error

<type 'exceptions.AttributeError'> 'NoneType' object has no attribute 'endswith'


Don't know what that is but I'm digging in right now to find out.

Anthony

unread,
Jun 22, 2012, 12:24:46 AM6/22/12
to web...@googlegroups.com
Can you show the traceback and the database field content that produced that error?

RKS

unread,
Jun 22, 2012, 12:36:27 AM6/22/12
to web...@googlegroups.com
Traceback:
Traceback (most recent call last):
File "gluon/restricted.py", line 205, in restricted
File "/Applications/web2py.app/Contents/Resources/applications/dev/views/default/blogs.html",
line 132, in <module>
File "gluon/template.py", line 919, in render
File "gluon/template.py", line 320, in __init__
File "gluon/template.py", line 720, in parse
File "gluon/template.py", line 454, in include
File "gluon/template.py", line 438, in _get_file_text
File "posixpath.pyc", line 62, in join
AttributeError: 'NoneType' object has no attribute 'endswith'

DB content:

(I'm trimming the HTML since it's a rather large post but if you think you need the rest of it I will post it too. However, leaving the ommitted HTML in and taking out the python resolves the problem so I don't think the HTML is to blame.)


<ul class="user_access">
                <li class="white">NEW USER?</li>
                <li><a href="{{=URL(signup')}}"><img src="{{=URL('static','images/button.png')}}" alt="" /></a></li>
            </ul>
            <ul class="user_access">
                <li class="white">CURRENT USER?</li>
                <li>{{=blog_form}}</li>
            </ul>
</div>
    <div class="wrapper">
        {{include 'default/postsviews3.html'}}
    </div>



\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
The postsviews3.html is just a standard HTML. The blog_form is defined in the controller and works outside of this scenario. Of course, the URLs also work outside of this instance.

Anthony

unread,
Jun 22, 2012, 1:33:39 AM6/22/12
to web...@googlegroups.com
What OS are you using? Maybe try:

{{import os}}
{{from gluon.template import render}}
{{=XML(render(blog.body, path=os.path.join(request.folder, 'views'),
  context
=response._vars))}}

Anthony

RKS

unread,
Jun 22, 2012, 10:46:31 AM6/22/12
to web...@googlegroups.com
Okay, so that works on everything except href="{{=URL('something')}} it returns the error "URL is not defined." I'm going to try the other anchor method available and see if that works.

The {{=blog.title}} and {{include 'postviews3.html'}} works fine with this solution.

Jonathan Lundell

unread,
Jun 22, 2012, 11:03:25 AM6/22/12
to web...@googlegroups.com
On Jun 22, 2012, at 7:46 AM, RKS wrote:
Okay, so that works on everything except href="{{=URL('something')}} it returns the error "URL is not defined." I'm going to try the other anchor method available and see if that works.

The {{=blog.title}} and {{include 'postviews3.html'}} works fine with this solution.



I think you might need to pass URL in with the context:

{{import os}}
{{from gluon.template import render}}
{{=XML(render(blog.body, path=os.path.join(request.folder, 'views'),
  context=dict(response._vars, URL=URL)))}}


(If this is a general issue, perhaps gluon.template ought to be importing URL and some of the other implicitly global symbols.)

Anthony

unread,
Jun 22, 2012, 11:24:04 AM6/22/12
to web...@googlegroups.com
How about replacing context=response._vars with context=globals()?

Anthony

RKS

unread,
Jun 25, 2012, 2:15:30 PM6/25/12
to
This all works, but I can't wrap my head around why everything after this snippet is no longer displayed. It does not even exist in the source. For example, my code is like this:

<div class="wrapper">

                {{import os}}
                {{from gluon.template import render}}
                {{=XML(render(blog.body,path=os.path.join(request.folder, 'views'), context=globals()))}}
                {{pass}}
        <!--start-->
         <div class="clear"></div>
            <ul class="user">

                <li class="white">NEW USER?</li>
                <li><a href="{{=URL('register')}}"><img src="{{=URL('static','images/button_register.png')}}" alt="Login/Register to comment!" /></a></li>
            </ul>
            <ul class="user">

                <li class="white">CURRENT USER?</li>
                <li class="blog_form">{{=blog_form}}</li>
            </ul>
            <div class="clear"></div>
        </div>

Everything from the inserted comment (<!--start-->) will not exist any more after this. Go back to simple {{=XML(blog.body)}} and everything after it displays fine. I've tried adding a pass, no pass, two passes, etc. But it still appears from that point web2py is not recognizing regular html anymore. Nothing after that will display at all.

RKS

unread,
Jun 25, 2012, 2:17:32 PM6/25/12
to web...@googlegroups.com
BTW, it's EVERYTHING in html after that snippet. It won't display the footer or anything.
Message has been deleted

Cliff Kachinske

unread,
Jun 26, 2012, 6:16:49 AM6/26/12
to web...@googlegroups.com
What is the purpose of this line of code?

                {{pass}}


What happens if you delete it?

RKS

unread,
Jun 26, 2012, 11:23:42 AM6/26/12
to web...@googlegroups.com
In that trial I was trying to end the python, thinking possibly it's affecting what follows. Deleting it does nothing.

Sort of like {{if:}},{{else:}},{{pass}}. I was just trying to make it render that python and then stop.

Anthony

unread,
Jun 26, 2012, 12:40:12 PM6/26/12
to web...@googlegroups.com
Just to be clear, are you saying web2py is not generating the HTML at all (i.e., if you do "view source" in the browser, the HTML simply isn't there), or is it that the content below that point is being generated but simply isn't being visually rendered by the browser (which could occur, for example, if your XML() object includes a closing </html> tag).

Anthony


On Monday, June 25, 2012 2:14:37 PM UTC-4, RKS wrote:
This all works, but I can't wrap my head around why everything after this snippet is no longer displayed. It does not even exist in the source. For example, my code is like this:

<div class="wrapper">
                {{import os}}
                {{from gluon.template import render}}
                {{=XML(render(blog.body,path=os.path.join(request.folder, 'views'), context=globals()))}}
                {{pass}}
        <!--start-->
         <div class="clear"></div>
            <ul class="user">
                <li class="white">NEW USER?</li>
                <li><a href="{{=URL('register')}}"><img src="{{=URL('static','images/button_register.png')}}" alt="Login/Register to comment!" /></a></li>
            </ul>
            <ul class="user">

                <li class="white">CURRENT USER?</li>

RKS

unread,
Jun 26, 2012, 12:57:30 PM6/26/12
to web...@googlegroups.com
View source does not show anything below the content inside that XML.

For example, I have a layout.html with the standard {{include}} {{ include footer.html}} etc.

The place where I have this XML element fall within the view that's extending this layout. So no matter what, there should be a footer at the very least. There's none. Even after the XML I have HTML within that view that no longer exists in source. The new source just ends after the content of blog.body like web2py no longer recognizes anything else.

That's why I added in the {{pass}} trying to force web2py to stop whatever it is doing to ignore the rest of the HTML.

There is no </html> since the data being called inside the blog.body is just a field from the db. I know I could have put a </html> in the field or in the included view it's calling but I double checked after reading your comment and there is none. All that html after the snippet is just like Keyser Soze.

Anthony

unread,
Jun 26, 2012, 1:45:12 PM6/26/12
to web...@googlegroups.com
Can you pack and attach a minimal application that reproduces the problem (use a SQLite db with at least one blog.body entry that demonstrates the problem)?

Anthony

RKS

unread,
Jun 26, 2012, 2:34:03 PM6/26/12
to web...@googlegroups.com
Here you go.
web2py.app.XMLtest.compiled.w2p

RKS

unread,
Jun 27, 2012, 4:09:45 PM6/27/12
to web...@googlegroups.com
Unless you're very curious about this problem I wouldn't try too hard. I'm under a deadline so I just used an if statement to wrap the include file I need and referenced the specific pages inside the if.

Might not be the most elegant way to do things and certainly it falls into the workaround way of doing it, but for now it's what I'm going to do.

Thanks, both of you, for all your help on this.

Anthony

unread,
Jun 28, 2012, 11:03:49 AM6/28/12
to web...@googlegroups.com
I would actually like to look into this, but the packed application you sent was compiled and doesn't include the original uncompiled code. Could you instead send the uncompiled version?

Anthony

RKS

unread,
Jun 28, 2012, 12:38:20 PM6/28/12
to web...@googlegroups.com
That's fine. I'm sorry for such a dumb mistake. Don't know why I did that. Here it is.

RKS

unread,
Jun 28, 2012, 12:40:59 PM6/28/12
to web...@googlegroups.com
Forgot to attach
web2py.app.XMLtest.w2p

Anthony

unread,
Aug 1, 2013, 10:15:02 AM8/1/13
to
It appears the render() function creates its own "response" object in the "context" passed to it, so when globals() is passed as the context, it overwrites the response object in the view environment. I think it works, however, if you move the code to the controller and pass the result to the view:

def blog_entry():
    import os
    from gluon.template import render
    blog = XML(render(blog.body, path=os.path.join(request.folder, 'views'), context=globals()))
   
return dict(blog=blog)

And in the view:

{{=blog}}

Anthony
Reply all
Reply to author
Forward
0 new messages