HTML─;通过CherryPy从表单子元素创建Python字典
当HTML表单提交给Python函数时,值将在一个字典中发送。对于HTML表单中的某些子元素,我想在该表单字典中发布一个附加的嵌套字典。问题是,如果有一个HTML标记或类似的东西,Python会将其解释为打开一个新字典。到目前为止,我试着给HTML─;通过CherryPy从表单子元素创建Python字典,python,html,forms,dictionary,cherrypy,Python,Html,Forms,Dictionary,Cherrypy,当HTML表单提交给Python函数时,值将在一个字典中发送。对于HTML表单中的某些子元素,我想在该表单字典中发布一个附加的嵌套字典。问题是,如果有一个HTML标记或类似的东西,Python会将其解释为打开一个新字典。到目前为止,我试着给命名,或者给一个不可见的命名,但当然没有这么简单。嵌套表单也不可能 我拥有的是一个表单,它包含一些文本输入和一个包含相关项目选择的表 # ! /usr/bin/env python # -*- coding: utf-8 -*- # image_slide.p
命名,或者给一个不可见的
命名,但当然没有这么简单。嵌套表单也不可能
我拥有的是一个表单,它包含一些文本输入和一个包含相关项目选择的表
# ! /usr/bin/env python
# -*- coding: utf-8 -*-
# image_slide.py
""" Python 2.7.3
Cherrypy 3.2.2
"""
beverages = {
'coffee': {
'beverage': 'coffee',
'time of day': 'morning',
'temperature': 'hot',
'color': 'brown',
'taste': 'full-bodied',
}
}
ingredients = {
'coffee': [
'coffee',
'sugar',
'milk',
'cinnamon',
],
}
yield(u'''
<form action="..." method="POST">
<table>
''')
for key, value in beverages['coffee'].items():
yield(u'''
<tr>
<td> {key}: </td>
<td> <input type="text" name="{key}" value="{value}">< /td>
</tr>
'''.format(locals(),)
如果我可以迭代kwargs['components']
,那就更好了:
for key, values in kwargs:
if key startswith('filename_'):
ingredients['coffee'][key[9:]] = value
我这样问是因为
标记比用Python的BeautifulSoup解析表更接近我当前的解决方案。我当然想知道。毕竟,有了BeautifulSoup,我现在可能已经完蛋了
编辑1:
这与web应用程序框架CherryPy一起运行。也许有一种方法可以处理这样的请求。
虽然我不认为它会提供一些不合标准的东西 编辑2: 考虑到表单字典在URL中以问号开头,我认为子字典是不可能的,因为我不知道任何字典结束字符。我能想到的最接近的方法是使用一个名为“index”的隐藏输入,并将其与名为“filename”的文本输入一起使用,不幸的是,PHP让我走上了正确的方向
for key, values in kwargs['ingredients'].items():
ingredients['coffee'][key] = value[filename]
.format(locals(),)
''.format(locals(),)
对于键,zip中的值(kwargs['index'],kwargs['filename']):
配料['coffee'][key]=价值
然而,这对删除按钮不起作用,我计划将其添加到每个配料中。由于只有提交输入可以携带索引,并且它的值用于显示按钮的unicode符号,因此我再次必须将索引附加到名称
然后,我能想到的唯一一件事,是每种成分的一种形式和公式的顶部,而不是每种成分的一种大形式。虽然我不知道这是否有利于性能,但如果配料表太长的话
作为一种视觉技巧,我们会想到一个背景图像来替换该值,然后可以根据其名称透明地使用该值。它相应的问题有助于它的工作
但这些都不能回答我的问题。我仍然缺少所有输入的一个解决方案,
喜欢多种形式,只是更优雅 好吧,我也想知道这是怎么做到的,给你。这只适用于单级DICT。如果你想让它递归,我就把它留给你 问题是:
是foo[bar]
是变量名,括号转换为URL安全实体:
'<input type="hidden" name="index" value="{index}"> '.format(locals(),)
'<input type="text" name="filename" value="{name}"> '.format(locals(),)
for key, values in zip(kwargs['index'], kwargs['filename']):
ingredients['coffee'][key] = value
CherryPy允许您通过在CherryPy.request.body.processors
中定义可调用的来定义,这是一个其键与内容类型匹配的字典。这就是()中的cherrypy.tools.json_
工具的工作原理,它将主体处理器替换为当请求的内容类型为application/json
时解析json的函数
您需要的最后一部分是如何将解析后的字典(即,{'foo':'bar'}
注入处理程序方法的参数中,以便与常规POST输入变量一样使用。我直接从默认的表单处理程序获取它:
这是一个工具。您需要在配置中启用它,并将其加载到服务器脚本中,但它需要一组dict形状的表单输入将dict传递给处理程序。它使用正则表达式来实现这一点
[DEBUG] BODY_TEXT: foo%5Bbar%5D=input_value
可爱的基于文本的表单!不是很相关,但你是如何制作的?@jh314,我没有制作。我只是用它来代替屏幕截图。不过这是个好主意。也许用一点CSS和一些图片,甚至滚动条都可以。
'<input type="hidden" name="index" value="{index}"> '.format(locals(),)
'<input type="text" name="filename" value="{name}"> '.format(locals(),)
for key, values in zip(kwargs['index'], kwargs['filename']):
ingredients['coffee'][key] = value
[DEBUG] BODY_TEXT: foo%5Bbar%5D=input_value
import re
import cherrypy
import logging
import urllib
class ImprovedFormInput(cherrypy.Tool):
def __init__(self):
logging.debug('ImprovedFormInput.__init__()')
cherrypy.Tool.__init__(self, 'before_request_body', self.handle_post, priority=50)
def handle_post(self):
logging.debug('ImprovedFormInput.handle_post()')
request = cherrypy.serving.request
def impfin_processor(entity):
raw_body = entity.fp.read()
body_text = raw_body.decode()
logging.debug('BODY_TEXT: %s', body_text)
parsed = urllib.parse.parse_qs(body_text)
logging.debug('PARSED: %s', parsed.keys())
form_inputs = {}
r = re.compile(r'^(\w+)\[(.+)\]$') # This pattern could be better
for key in parsed.keys():
m = r.match(key)
if m is None:
continue
groups = m.groups()
pkey = groups[0]
logging.debug('PKEY: %s', pkey)
ckey = groups[1]
logging.debug('CKEY: %s', ckey)
if pkey not in form_inputs:
form_inputs[pkey] = {}
form_inputs[pkey][ckey] = parsed[key]
logging.debug('FINPUTS: %s', form_inputs)
# https://github.com/cherrypy/cherrypy/blob/main/cherrypy/_cpreqbody.py#L177
for key, value in form_inputs.items():
if key in entity.params:
if not isinstance(entity.params[key], list):
entity.params[key] = [entity.params[key]]
entity.params[key].append(value)
else:
entity.params[key] = value
request.body.processors['application/x-www-form-urlencoded'] = impfin_processor