CherryPy将查询字符串值与POST主体中的表单值相结合

时间:2015-07-09 07:23:22

标签: python forms query-string cherrypy

我正在维护别人的旧的CherryPy代码,并且有一个我想要了解的有趣情况。请考虑以下代码来演示它:

com.sothree.slidinguppanel.SlidingUpPanelLayout

使用import cherrypy class HelloWorld(object): def index(self, name): html = """<form method="post"> <input type="text" name="name" value="%s" /></form> Hello %s!""" % (name, name) return html index.exposed = True cherrypy.quickstart(HelloWorld()) 运行它并转到http://127.0.0.1:8080/?name=foo。输出是一个文本输入框,带有“foo”,后跟“Hello foo!”。

但是,如果我在框中编辑文本并将其替换为“bar”并按Enter键(提交表单),则结果不是输入框中的“bar”和“Hello bar!”下面但是(为ascii艺术输入框道歉):

python hello.py

似乎CherryPy正在将URL查询字符串“name”参数值与POST请求正文中提交的表单“name”值相结合,并为暴露的index()方法提供带有这两个值的列表。

从我所知道的我正在维护的代码,它并不总是这样。这导致了我的两个问题:

  1. 在3.7.0之前的某个版本中,CherryPy是否改变了它处理这种情况的方式(这是我正在测试的)?
  2. 我是否可以将CherryPy配置为恢复旧的行为,或者至少让POST值覆盖查询字符串值?
  3. (我对CherryPy文档并不熟悉,但我找不到答案。)

3 个答案:

答案 0 :(得分:2)

我找到了我提出的问题1的答案。

随着CherryPy 3.2的发布,行为发生了变化。实际更改是在2009年5月31日的git commit e05feef4fee7df1ee5d25d11393f872c9ef12510(hg:3b92b5aa76f9)中进行的,这是在切换_cpreqbody模块以代替旧的process_body()方法时。

用于执行此操作的代码(其中self.params是一个dict,已包含查询字符串中的参数):

        self.body_params = p = httputil.params_from_CGI_form(forms)
        self.params.update(p)

从3.2开始,它现在执行此操作(其中keyvalue来自正在处理的POST正文):

        if key in params:
            if not isinstance(params[key], list):
                params[key] = [params[key]]
            params[key].append(value)
        else:
            params[key] = value

看起来我的问题2没有简单的答案,所以当我知道我所追求的价值所在的位置时,我将不得不使用cherrypy.request.body_params

答案 1 :(得分:1)

我认为这不是3.x系列的变化。您可以直接访问GET和POST参数,如下面的代码段所示。但是,建议使用唯一名称,并且不要容易出错。

import urlparse
import cherrypy

class HelloWorld:

  @cherrypy.expose
  def index(self, name):
    postParams = cherrypy.request.body.params
    getParams  = urlparse.parse_qs(cherrypy.request.query_string)
    print(postParams, getParams)
    # ({u'name': u'bar'}, {'name': ['foo']})

更新

好的研究@TimB。通过跳过代码库,我无法找到事情发生的位置。是的CherryPy 3.2+就像这个系列一样。

CherryPy是完全可配置的,当你能够处理它的概念时,你的情况也不例外。具体来说,您可以编写一个CherryPy工具来覆盖POST参数的混合请求参数。这只是几行。

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import urlparse

import cherrypy


config = {
  'global' : {
    'server.socket_host' : '127.0.0.1',
    'server.socket_port' : 8080,
    'server.thread_pool' : 8
  },
  '/' : {
     'tools.postoverride.on' : True,
   }
}

def postOverride():
  cherrypy.request.params.update(cherrypy.request.body.params)

cherrypy.tools.postoverride = cherrypy.Tool('before_handler', postOverride)


class HelloWorld:

  @cherrypy.expose
  def index(self, name):
    html = """<form method="post">
      <input type="text" name="name" value="%s" /></form>
      Hello %s!""" % (name, name)
    return html


if __name__ == '__main__':
  cherrypy.quickstart(HelloWorld(), '/', config)

答案 2 :(得分:0)

我确实得到了您的预期结果。我想你的代码有问题。

特别是你使用

% (name, name)

哪个无法解析为两个不同的值。