Again: how redirect without propagate the .load extension?

621 views
Skip to first unread message

Martin Weissenboeck

unread,
Jul 27, 2012, 12:16:54 PM7/27/12
to web...@googlegroups.com
From the book:
If you LOAD a component having the .load extension and the corresponding controller functionredirects to another action (for example a login form), the .load extension propagates and the new url (the one to redirect too) is also loaded with a .load extension.

I have a chain LOADs (one LOAD loads another, depending on the input), but at the end of the work there should be a redirect without any ".load".
Yes, I have read some threads (e.g. http://comments.gmane.org/gmane.comp.python.web2py/68401)

Anthony wrote:

Your component isn't redirecting, so this is not due to the propogation of the .load extension upon redirect. However, the URL function will automatically use the extension of the current request if the extension isn't specified (unless the extension of the current request is html). Since the request that loads the component has a .load extension, the URL function will automatically add a .load extension as well. To avoid this, just specify an explicit extension (e.g., extension='html'). Note, if you want the link to point to an html page, but you don't want the resulting URL to actually include the .html extension, then you can explicitly set extension=False. In that case, web2py will default to requesting the .html view (as it always does when there is no url extension), but it won't show .html in the URL.

I have tried a code like this (shortened):
def index():...
def sub1():...


def sub2():
    form=FORM(
        INPUT(_type='text', _name='tsub2'),
        INPUT(_type='submit'),
        )
    if form.accepts(request, session):
        return dict(form=LOAD('default','sub3.load',ajax=True,vars={'text':form.vars.tsub2}))
       
    return dict(form=form)

def sub3():
    redirect(URL('index2',extension='html',vars={'text':request.vars.text}))

but I did not get a new page "index2". I got the "old" page ("index") with the content of index2.html at the end.
Any ideas what is wrong?

Regards, Martin






Bruno Rocha

unread,
Jul 27, 2012, 12:45:10 PM7/27/12
to web...@googlegroups.com
put extension=False in URL

redirect(URL('index2',extension='html',vars={'text':request.vars.text}, extension=False))

Martin Weissenboeck

unread,
Jul 27, 2012, 2:43:07 PM7/27/12
to web...@googlegroups.com
I have tried:
redirect(URL('index2',
vars={'text':request.vars.text}, extension=False))
Sorry, the same result - index2 is "loaded".


2012/7/27 Bruno Rocha <rocha...@gmail.com>

Niphlod

unread,
Jul 27, 2012, 2:56:39 PM7/27/12
to web...@googlegroups.com, mar...@weissenboeck.at
I've not tested it, but there's a misunderstanding here I think.

Say that "URL() gets the extension from the current request if not specified" is true. This is generally "wanted" because links in a LOADed portion of the frame must not contain the whole layout.

But I think you want a LOADed form to submit and redirect to a "full" page (i.e. with fully loaded layout). This means to load in a portion of the page a form and when submit redirect to another page, not "retaining" the one that loaded the form in the first place.
i.e. in the browser address bar you want to jump from /index - where /sub2 is loaded - to /sub3 that will redirect to /index2
vs
being stuck to /index

This is not the default behaviour and is managed by the ajax_trap parameter, that is assumed to be True for ajax=True.

Did you try your code with ajax=True and ajax_trap=False ?

Johann Spies

unread,
Jul 27, 2012, 4:01:50 PM7/27/12
to web...@googlegroups.com
Hallo Martin,

In stead of redirecting, I am using this script in the view:

<script type="text/javascript">
jQuery(document).ready(function() {
jQuery($(":input:submit:last").addClass('gaanvoort'));
jQuery($("input.gaanvoort").click(
function() {
window.location = "/init/articles/add_article";
}));

});
</script>


and then use session variables on the destination.

Regards
Johann
--
Because experiencing your loyal love is better than life itself,
my lips will praise you.  (Psalm 63:3)

Martin Weissenboeck

unread,
Jul 27, 2012, 5:15:22 PM7/27/12
to web...@googlegroups.com
You have described my problem nearly perfect, with one difference:
There is a path from index to sub1, from sub1 to sub2 and from sub2 to sub3, every step should use the LOAD-function. Every step adds some information. After the last step the whole information should be sent to index2 (using session variables), but the last page (index2) should be a new page with a new view. Therefore I have tried a "redirect".

No, ajax_trap=False did not work, I have tried it - but thank you for the proposal.
The book says:

ajax_trap is ignored and assumed to be True if ajax=True.

2012/7/27 Niphlod <nip...@gmail.com>
--
 

Martin Weissenboeck

unread,
Jul 27, 2012, 5:54:51 PM7/27/12
to web...@googlegroups.com
Hallo Johann,

I have tried your proposal - yes, this "workaround" does the job and I think I will use it.
But I am surprised that there is not simple solution. Or does nobody else want to get rid the "load"?

2012/7/27 Johann Spies <johann...@gmail.com>

Massimo Di Pierro

unread,
Jul 27, 2012, 6:43:30 PM7/27/12
to web...@googlegroups.com, mar...@weissenboeck.at
I will take a patch. ;-)

Martin Weissenboeck

unread,
Jul 29, 2012, 1:43:51 AM7/29/12
to web...@googlegroups.com
Thank you!

2012/7/28 Massimo Di Pierro <massimo....@gmail.com>

Martin Weissenboeck

unread,
Aug 8, 2012, 4:58:44 AM8/8/12
to web...@googlegroups.com
Any solution so far?

2012/7/29 Martin Weissenboeck <mwei...@gmail.com>

Anthony

unread,
Aug 8, 2012, 9:21:33 AM8/8/12
to web...@googlegroups.com, mar...@weissenboeck.at, Massimo Di Pierro
Attached is a patch that enables client-side full-page redirects from Ajax requests. It alters the redirect() function in http.py as well as adding an event handler in web2py.js. With it, in a function called via Ajax, you can do:

def my_ajax_function():
   
if some_condition:
        redirect
(URL('default', 'other_function', extension=False), type='client')
   
return dict()

In that case, redirect does not raise an HTTP(303). Instead, it raises an HTTP(200) and sets a special "web2py-redirect-location" response header with the redirect URL. On the client side, a jQuery.ajaxSuccess event handler checks for that header on every successful Ajax request, and if the header is there, it sets window.location to that URL, which loads the full page in the browser window. Note, if redirecting from a function called with the .load extension, you probably want to set extension=False when constructing the redirect URL so the .load extension is not propagated to the redirect.

Eventually, we might consider adding a type='internal' option to the redirect() function, which could generate a new internal request to the redirect URL rather than sending a 303 to the server (this would have nothing to do with Ajax -- just a way of speeding up regular server-side redirects when you don't need the browser to receive a new URL with the redirect).

Anthony
client_redirect.patch

Massimo Di Pierro

unread,
Aug 8, 2012, 11:05:42 AM8/8/12
to web...@googlegroups.com, mar...@weissenboeck.at, Massimo Di Pierro
In trunk, with a minor change that makes the type parameter optional and auto-detects ajax.

Anthony

unread,
Aug 8, 2012, 11:30:06 AM8/8/12
to web...@googlegroups.com, mar...@weissenboeck.at, Massimo Di Pierro
On Wednesday, August 8, 2012 11:05:42 AM UTC-4, Massimo Di Pierro wrote:
In trunk, with a minor change that makes the type parameter optional and auto-detects ajax.

I don't think it should auto-detect ajax and automatically do a client-side full-page redirect in that case. Note, you don't necessarily want a full page redirect with all Ajax requests (when an Ajax component redirects, for example, you typically want the redirect response to load in the component, not the full page). This is just supposed to be an option for those subset of cases where you do need a full-page redirect from an Ajax response.

Anthony

Massimo Di Pierro

unread,
Aug 8, 2012, 1:18:11 PM8/8/12
to web...@googlegroups.com, mar...@weissenboeck.at, Massimo Di Pierro
ok, I defaulted to type='http' as you did but I allowed a type='auto' as well.

Anthony

unread,
Aug 8, 2012, 3:04:13 PM8/8/12
to web...@googlegroups.com, mar...@weissenboeck.at, Massimo Di Pierro
On Wednesday, August 8, 2012 1:18:11 PM UTC-4, Massimo Di Pierro wrote:
ok, I defaulted to type='http' as you did but I allowed a type='auto' as well.

Good idea. Actually, I'm not sure we need the separate "auto" option -- type='client' only makes sense for Ajax requests anyway, so why not just make "client" behave like "auto" (i.e., when type == "client", ignore the type unless it's an Ajax request):

    from gluon import current
   
if type == 'client' and current.request.ajax:
         
raise HTTP(200, **{'web2py-redirect-location': location})

Also, I'm re-thinking whether we should go with a "type" argument that can take multiple values or a simple boolean (e.g., client_side=True). I was originally thinking "type" could be extended to take an "internal" value, but perhaps client-side and internal should be considered to be independent rather than mutually exclusive (i.e., you might want a redirect to be both internal, and client-side -- after the internal redirect to generate the response, the redirect itself should still happen on the client in the full window). In that case, we'd need a separate argument to specify "internal" independently (i.e., internal=True, client_side=True), so the client-side specification might as well just be a boolean. Thoughts?

Anthony

Massimo DiPierro

unread,
Aug 8, 2012, 3:20:13 PM8/8/12
to Anthony, web...@googlegroups.com, mar...@weissenboeck.at
I agree. Please check trunk again.

Anthony

unread,
Aug 8, 2012, 3:26:31 PM8/8/12
to web...@googlegroups.com, Anthony, mar...@weissenboeck.at
Looks good. :-)
Reply all
Reply to author
Forward
0 new messages