3

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

<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>

提交表单时,会调用视图类。

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

现在,问题是我无法将逻辑放入__init__方法中,因为该方法被多次调用,导致只需单击一次即可提交多个表单。但是,__call__单击按钮时会调用一次该方法,但不幸的是,如果我单击链接以查看视图中的当前内容项,则没有任何反应,因为__call__调用了该方法并且没有任何反应。

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

self.context.REQUEST.response.redirect( self.context.absolute_url() )

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

4

1 回答 1

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>

输入filename框 tal 表达式可以只使用路径表达式,这些对字典都适用。

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

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

def __call__(self):
    if 'form.action.convert' in self.request.form: 
        self.convert_document()

因为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())

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

请注意,如果您确实覆盖了具有关联模板__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
于 2012-10-16T09:07:18.943 回答