我有一个带有 View 类的页面模板。在页面模板中,我有一个提交到同一页面的按钮,即
<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>
提交表单时,调用 View 类。
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__
方法,但不幸的是,如果我单击一个链接以查看 View 中的当前内容项,则没有任何反应,因为 __call__
方法被调用但没有任何反应。
我不能在 __call__
方法中使用下面的代码。浏览器会提示页面正在以一种永无止境的方式重定向。
self.context.REQUEST.response.redirect( self.context.absolute_url() )
在 Plone 的页面模板中是否有更好的处理表单提交的方法?如何从页面模板调用 View 类中的方法(即 convert_document
)?
最佳答案
首先,对你的代码进行一些评论,它可以简化和改进:
最佳做法是让您的表单使用 View 的 absolute_url()
方法;这是规范的 URL,而 request/getURL
可能包含获取异常或如果您的 View 包含在其他地方则完全错误的 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
是你 View 的一个方法,它本身可以访问 self.context
和 self.request.form['filename']
,简化您的方法签名。由于您现在知道您的表单已提交,您可以指望 self.request.form['filename']
存在并且是一个字符串;如果不是有人手动修改了请求,那么事情就应该中断,所以在这种情况下我通常不会使用 get(..., '')
。
View 必须始终在 __call__
方法中完成所有工作,因为 __init__
在遍历期间被调用,此时像当前用户这样的关键信息还没有被确定。您不需要通过上下文访问 redirect
方法的响应,只需从 self.request
属性访问它即可,但请记住 return 结果:
return self.request.response.redirect(self.context.absolute_url())
但是,如果您的 View 是上下文对象的默认 View ,那确实会导致浏览器无法容忍的重定向循环。
请注意,如果您确实覆盖了具有关联模板的 BrowserView
View 类的 __call__
方法,则需要确保返回模板在适当的地方。因此,我对您的 View 类的尝试是:
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
关于python - 在 Plone 模板中处理表单提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12910348/