Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

doGet、doPost

Pageクラスにごにょごにょする時にどこにロジックをかけばいいかよくわからんってことになるので明示的に実装
させるところを決めてみる。
はじめてzope.interface使ったよ。
しびれる〜。

import random

from time import time as now

import twisted.python.components as tpc
from twisted.python.components import registerAdapter

from nevow import rend
from nevow import inevow
from nevow import util

from zope.interface import implements
from zope.interface import Interface

class IFlash(Interface):
    pass

class BasePage(rend.Page):

    def __init__(self, *args, **kwargs):
        self.callback_args = args
        self.callback_kwargs = kwargs

    def locateChild(self, ctx, segments):
        request = inevow.IRequest(ctx)
        method = request.method

        if method == 'POST':
            method = getattr(self, 'onPost', None)
            return self.doProcessPost(ctx, method, '')
        return super(BasePage, self).locateChild(ctx, segments)
    
    def beforeRender(self, ctx):
        request = inevow.IRequest(ctx)
        method = request.method
        if method == 'GET':
            f = getattr(self, 'onGet', None)
            if f:
                self.onGet(ctx, *self.callback_args, **self.callback_kwargs) 

    def doProcessPost(self, ctx, method, bindingName):
        
        def redirectAfterPost(aspects):
            hand = aspects.get(inevow.IHand)
            refpath = request.getHeader('referer') or ''
            if hand:
                if isinstance(hand, rend.Page):
                    print hand
                elif isinstance(hand, basestring):
                    refpath = hand
            
            from nevow import url 
            refpath = url.URL.fromString(refpath)
            magicCookie = '%s%s%s' % (now(),request.getClientIP(),random.random())
            refpath = refpath.replace('_nevow_carryover_', magicCookie)
            rend._CARRYOVER[magicCookie] = C = tpc.Componentized()
            for k, v in aspects.iteritems():
                print k, v
                C.setComponent(k, v)
            print "redirect path %s" % str(refpath)
            request.redirect(str(refpath))
            from nevow import static
            return static.Data('You posted a form to %s' % bindingName, 'text/plain'), ()
        
        request = inevow.IRequest(ctx)
        return util.maybeDeferred(method, ctx, *self.callback_args, **self.callback_kwargs
            ).addCallback(self.onPostSuccess, request, ctx, bindingName,redirectAfterPost
            ).addErrback(self.onPostFailure, request, ctx, bindingName,redirectAfterPost)        

    def onPostSuccess(self, result, request, ctx, bindingName, redirectAfterPost):
        if result is None:
            message = "%s success." % formless.nameToLabel(bindingName)
        else:
            message = result
        flash = {}
        try:
            flash = IFlash(ctx)
        except:
            pass
        return redirectAfterPost({inevow.IHand: result, inevow.IStatusMessage: message, IFlash: flash})
    
    def setFlash(self, ctx, obj):
        ctx.remember(obj, IFlash)
    
    def getFlash(self, ctx):
        obj = None
        try:
            obj = IFlash(ctx)
        except:
            pass
        return obj

def flashFactory(ctx):
    co = rend._CARRYOVER.get(
        ctx.tag.args.get('_nevow_carryover_', [None])[0], None)
    return IFlash(co, None)


registerAdapter(util._namedAnyWithBuiltinTranslation('form.flashFactory'),
                util._namedAnyWithBuiltinTranslation('nevow.context.RequestContext'),
                util._namedAnyWithBuiltinTranslation('form.IFlash'))

GETでアクセスされた場合はdoGet、POSTの時はdoPostが呼ばれる。
resolverを使ってるとurlでマッチングした値が引き数に入ってくる。
Flashは特に何もしてない。好きなオブジェクトを突っ込むだけ。
基本的にはPRGパターンを想定してるのでこんな実装になっている。
サンプルはこんな感じ。

class SimplePage(form.BasePage):
    #addSlash=True
    docFactory=loaders.xmlfile(util.sibpath(__file__, 'templates/sample.html'))
    
    def onGet(self, ctx, id):
        print "GGGGGGGGGGGGGGGGGGGGGET %s" % id
        a = self.getFlash(ctx)
        print a

    def onPost(self, ctx, id):
        print "PPPPPPPPPPPPPPPPPPPPOST %s" % id
        self.setFlash(ctx, "TEST")

        return "/index/45/"

うくく。