处理Plone模板中的表单提交

Fra*_*ine 3 python plone

我有一个带有视图类的页面模板.在页面模板中,我有一个提交到同一页面的按钮,即

<form method="post" tal:attributes="action request/getURL" >
    <input type="hidden" name="filename" value="" tal:attributes="value python:item['filename']" />
    <input type="submit" name="form.action.convert" value="Convert" /> 
</form>
Run Code Online (Sandbox Code Playgroud)

提交表单时,将调用视图类.

class Html(BrowserView):

    def __init__(self, context, request): 
        self.request = request
        self.context = context         

    def __call__(self):
        # Is this a form submission via POST?
        req = self.request
        if req.get('REQUEST_METHOD', 'POST') and \
            req.form.get('form.action.convert', '') == 'Convert': 

            self.convert_document(self.context, str(req.form.get('filename', '')))


    def convert_document(self, contextObj, fileToConvert):
       """ Do something """
       return None
Run Code Online (Sandbox Code Playgroud)

现在,问题是我无法将逻辑放在__init__方法中,因为多次调用此方法,只需单击一次就可以生成多个表单.但是,__call__单击该按钮时会调用该方法一次,但遗憾的是,如果单击链接以查看视图中的当前内容项,则不会发生任何事情,因为该__call__方法被调用且没有任何反应.

我不能在__call__方法中使用下面的代码.浏览器会抱怨页面以永不停止的方式重定向.

self.context.REQUEST.response.redirect( self.context.absolute_url() )
Run Code Online (Sandbox Code Playgroud)

在Plone的页面模板中处理表单提交有更好的方法吗?如何convert_document从页面模板中调用视图类中的方法(即)?

Mar*_*ers 6

首先,对您的代码进行一些评论,可以简化和改进:

最佳做法是让您的表单使用absolute_url()您的视图方法; 它是规范的URL,request/getURL如果您的视图包含在其他地方,则可能包括获取奇怪或错误的URL:

<form method="post" tal:attributes="action view/absolute_url" >
    <input type="hidden" name="filename" value="" tal:attributes="value item/filename" />
    <input type="submit" name="form.action.convert" value="Convert" /> 
</form>
Run Code Online (Sandbox Code Playgroud)

filename输入框TAL表达式可以只使用一个路径表达式,这些工作的字典就好了.

您不需要重新定义该__init__方法,BrowserView该类已经为您提供了该方法.

为了测试表单是否已提交,我们通常只测试请求中存在的提交按钮,您的测试比需要的更详细:

def __call__(self):
    if 'form.action.convert' in self.request.form: 
        self.convert_document()
Run Code Online (Sandbox Code Playgroud)

因为它convert_document是一种视图方法,它本身可以访问self.contextself.request.form['filename']简化方法签名.既然您现在知道您的表单已提交,那么您可以指望self.request.form['filename']存在并成为一个字符串; 如果不是某人已经手动修补请求而且事情应该破坏,所以我通常不会get(..., '')在这种情况下使用.

视图必须始终在__call__方法中完成所有工作,因为__init__在遍历期间调用视图,此时此类关键信息尚未确定.您不需要redirect通过上下文访问该方法的响应,只需从self.request属性访问它,但记得返回结果:

return self.request.response.redirect(self.context.absolute_url())
Run Code Online (Sandbox Code Playgroud)

但是,如果您的视图是上下文对象的默认视图,那么这确实会导致浏览器无法容忍的重定向循环.

请注意,如果您覆盖具有与之关联的模板__call__BrowserView视图类的方法,则需要确保在适当的位置返回模板的输出.因此,我对你的观点课的刺激是:

class Html(BrowserView):
    def __call__(self):
        if 'form.action.convert' in self.request:
            self.convert_document()
            return self.request.response.redirect(self.context.absolute_url())
        return self.index()

    def convert_document(self):
       """ Do something """
       context = self.context
       filename = self.request.form['filename']
       # Do something with the context and filename
Run Code Online (Sandbox Code Playgroud)