[Twisted-web] Rendering after posts

Donovan Preston dp at ulaluma.com
Fri Jan 14 20:09:03 MST 2005


On Jan 14, 2005, at 5:04 PM, Michael Wilson wrote:

> In all the examples I've seen, the "way" to render a page after a post
> appears to be to set a redirect:
>
>         request.setComponent(iformless.IRedirectAfterPost, "/")
>
> (from examples/userdb.tac)
>
> If I want to include some additional variables in the redirected page,
> it seems like that's implemented by passing parameters on the redirect
> in the URL.
>
> Is there another way to render another page after a post, WITHOUT
> using redirect? (I've tried setting docfactory again, or returning
> another instance of rend.Page, but those don't seem to work.

The thing you return from the autocallable is available as IHand(ctx) 
during the redirected-to web request. The generally accepted way of 
rendering a different page upon redirect is to return it and then do 
something like this in your base class:

def locateChild(self, ctx, segments):
     renderAfterPost = IHand(ctx, None)
     if compy.implements(renderAfterPost, IResource):
         return renderAfterPost, ()
         ## If you just want to render the thing returned from the 
autocallable without
         ## doing any further url traversal, return () as the segments 
and renderAfterPost
         ## will be used to render this request.
         ... call the superclass ...

This results in servers whose page contents change depending on whether 
a form was posted recently, which I don't particularily like. Another 
way to do it would be to reserve a special url of the site for 
rendering "after post status" pages. In your autocallable, set 
IRedirectAfterPost to some url which never changes, like "/hand". Then, 
make the following Page available from that url (probably by setting 
the child_hand class attribute to an instance of the following class, 
on your root page):

class HandPage(object):
     def locateChild(self, ctx, segments):
         return NotFound

     def renderHTTP(self, ctx, segments):
         renderAfterPost = IHand(ctx, None)
         if compy.implements(renderAfterPost, IResource):
             return renderAfterPost.renderHTTP(ctx)
         return "No hand to render."

Since people generally seem to want to be able to do this, even though 
formless was designed to be rest-style and this trick doesn't really 
fit, I will probably be putting the first trick directly into 
rend.Page. This way, returning a Page from any autocallable would Just 
Work, even if it means that page will only render in that way on the 
first redirect after the form post.

(BTW, the above technique still does a redirect, even though you'd 
explicitly asked for a way to do this without redirecting -- I'll think 
about whether returning a Page from an autocallable should result in 
the posted-to URL rendering that Page, or the original, redirected-to 
URL rendering that Page)

dp




More information about the Twisted-web mailing list