1
2
3
4
5
<select name="myselect" id="myselect">
<option value="opt1">选项1</option>
<option value="opt2">选项2</option>
<option value="opt3">选项3</option>
</select>
1
2
3
4
$("#myselect").change(function(){
var opt=$("#myselect").val()
...
})
1. 编辑: 如果你想始终呈现字段禁用某些选项,你必须创建自己的自定义窗口小部件,并现场提供的渲染器。 当前渲染器只需要三个选项在它的元组的选择:(value, name, selected)。 你会需要修改,接受第四个可选的禁用。 基于在wtforms.widget选择类:class SelectWithDisable(object):"""
Renders a select field.
If `multiple` is True, then the `size` property should be specified on
rendering to make the field useful.
The field must provide an `iter_choices()` method which the widget will
call on renderingthis method must yield tuples of
`(value, label, selected, disabled)`.
"""
def __init__(self, multiple=False):
self.multiple = multiple
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = 'multiple'
html = [u'<select %s>' % html_params(name=field.name, **kwargs)]
for val, label, selected, disabled in field.iter_choices():
html.append(self.render_option(val, label, selected, disabled))
html.append(u'</select>')
return HTMLString(u''.join(html))
@classmethod
def render_option(cls, value, label, selected, disabled):
options = {'value': value}
if selected:
options['selected'] = u'selected'
if disabled:
options['disabled'] = u'disabled'
return HTMLString(u'<option %s>%s</option>' % (html_params(**options), escape(unicode(label))))
然后根据在wtforms.fields代码,子类已经存在的SelectFieldclass SelectFieldWithDisable(SelectFiel):
widget = widgets.SelectWithDisable()
def iter_choices(self):
for value, label, selected, disabled in self.choices:
yield (value, label, selected, disabled, self.coerce(value) == self.data)
注意:这不是测试或甚至可以运行Python代码,而是一个非常快速破解给出的问题,并从WTFORMS底层代码。但它应该给你足够的头部与答案完全控制现场开始沿。 使用CSS和JavaScript来控制呈现在页面上。 无论在什么模板渲染系统(I'瓶中 CodeGo.net,神社和wtforms)您呈现您提供一个id或class属性,当你渲染。 (我只是打印form.select_field_variable_name) 然后生成一个CSS文件来控制你的建模JavaScript来控制某些等定制禁用 编辑: 如果你有:<select id=selector>
<option id=value1 value=1>Bananas</option>
<option id=value2 value=2>Corn</option>
<option id=value3 value=3>Lolcats</option>
</select>
您可以将背景色:<style>
#selector {background-color: #beef99}
</style>
并启用/禁用与:<script>
option = document.getElementById('value3')
option.disabled = true
</script>
没看form有关的源码,但是应该是这样的∶首先,你得理解像flask这种MVC(或者说MTC)的基本运行机制。
- 对于flask的view,你得知道wsgi协议(如果不清楚,请自行Google之)。
更底层(逻辑上的底层)的HTTP utils(flask用的是werkzeug)将client端的HTTP requests等进行parse,并且将其构建为wsgi的environment(包含了request及其他信息)。
wsgi
server在process请求的过程是:根据wsgi协议构建environ,将其传入flask app
instance(这个即为flask框架实现的wsgi app),flask app
instance用这个environ和自己的``start_response``
method(这个也是uwsgi协议规约)完成请求处理并response。
flask有一个线程级(或greenlet)的request对象。在真正process response之前,将environ丢到这个request对象里,之后这个request跟着你的那个线程就成为了默契的炮友~~直至response完成或线程完蛋。
views里面的那一坨坨的route的作用是啥捏?这个就是url routing了,就是我在你的站点上点了一个特定的url,flask要如何满足你。你得说出你想要的东西吧。
那么views是什么时候用到呢?废话,当然还是在接收并理解请求之后到响应之前。
好
了,flask app instance在处理你的需求的时候从request对象里拿到了你请求的url,这个就相当于一把key,然后app
instance根据这个key去views里找到了对应的锁(你想要的处理逻辑,就是views里的route下面的function),这个锁啊,她
一旦被打开了,满足你需求的时刻也就快了 ~ ~
P.S. 至于如何匹配到这个锁的呢,这个就是url mapping了,就是一堆正则匹配(别小看这个,如果你用过flask的blueprint,你会明白写这么个mapping也是件爽hi了的事情咯)
- model &controller呢?
你的需求其实就是要flask给你response,response其实呢就是数据(不管是RESTFUL API还是template形式,都是你撸出的data)。
数据这坨翔实怎么来的呢?就是你从数据库(广义,包括sql &nosql db,内存级缓存,磁盘文件等等等等)拿到的,至于data的来源嘛,可能是你自己插的,或者是从别的地方哭着要来的。
model
就是干这活的,只不过它比较抽象,将数据库 *** 作转成了对Python对象的 *** 作(这个就是大名鼎鼎的ORM,其实并没有什么卵用,ORM写多了你连查询优
化都忘了,如果你有比较高的performance需求也有很多时间,就自己撸高效检索方案吧,我没少被这玩意儿坑%>_<%)。
controller这玩意儿你其实可以不要,不过为了做逻辑分离,让你撸业务撸的漂亮点儿还是用它吧。
OK,说了这么多,不知道有没有人能看懂,如果没看懂,让我思考会儿吧 ~ ~
========================================================================
简而言之呢,你用flask作application的时候,MVC各司其职堆好你产生data的逻辑即可,其它你一概不用管。
靠,终于可以回到你的问题上了:
先看下Form这玩意儿:
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
class NameForm(Form):
name = StringField('What is your name?', validators=[Required()])
submit = SubmitField('Submit')
这就是一个类而已,和model里面的那些玩意儿没本质区别,也都是一个映射关系。model是将数据库啥的和Python对象映射;Form是将HTML表单(form)和这个从flask.ext.wtf.Form及其子类映射。
再来看看这玩意儿:
1 @app.route('/', methods=['GET', 'POST'])
2 def index():
3 name = None
4 form = NameForm()
5 if form.validate_on_submit():
6 name = form.name.data
7 form.name.data = ''
8 return render_template('index.html', form=form, name=name)
首先来分析一下执行过程:
哎呀,这个只是个route嘛,它哪有执行过程。
执行是由app instance做的嘛,好吧,其实它是被app instance做的。
在
展开之前看一下route后面那个 methods=['GET',
'POST']。这玩意的意思是说,当我遇到有与``index``(即上面route下面的那个index)匹配的的请求时,我可以用GET或者
POST方法,其他的像PUT、DELETE等HTTP verb我不让你丫玩儿。
当你把你的这个flask应用deploy到web server或者在本地run test server的时候,你在浏览器里输入 http://xxxxxx.ooooo.xxoo/index 的时候,你向server发射的是``GET``炮d,flask instance接受了你的d,然后route到了index这个函数,好吧,激动人心的时刻到了:
#3. name = None 这个就是个赋值
#4. form = NameForm() 好吧,这个就是NameForm类的实例化,拿到一个form object。
#5.
if form.validate_on_submit():呵呵,这个嘛,意思是问一下#2中实例化的form
object,SB,你是在被人(1)submit(提交)并且(2)提交满足我的要求么?
好吧,前面说过了,我是在GET,而没有在submit(submit在HTML中为POST),好吧,我连(1)都不满足,所以也就没有#6、#7什么
事儿了。
#8 好的,app instance终于快要向你回馈了。给我把前面的from object和name变量一起带到index.html这个文件里吧。
哈哈,终于有jinja2的活儿了,@题主, 你丫也把index.html发上来呀 = =
index.html
里你写了个表单,里面有个叫做``name``的field和一个``submit``按钮,这些field和你的``NameForm``对应,好了,
对应填充的活儿和就交给jinja2吧,它会给你一个最终将在用户浏览器显示的index.html。
view的使命完成了,它成功的生成了数据。
app instance 拿到了view的数据,也该向client端发最终响应了。OK,server完成了这次request的response,用户拿到最终想要的东西了。
浏览器或者UA干的活儿我就不展开了,我的手已经抽筋了,
现在在用户的浏览器上,看到了index.html,上面有一个表单,那个表单上面有个文本框(有``What is your name?``的placeholder)和一个Submit提交按钮。
好
了,用户在那个文本框中写了一个名字,比如``John``,然后按了那个``Submit``按钮,这次提交回向server发射一个``POST``
请求,这个请求里面会带上文本框的名字(哈哈,就是name)和文本框name里面的值(yeah,就是``John``)。然后呢,到flask
instance中,request对象(如果不知道这是什么东西,看前文)里就会有所有这些有关请求的数据了。
辣么,辣么这跟from有毛线关系呢????
其实吧,form中的数据是flask从request(request是从environ构建的)中拿到并映射进form属性中的(映射过程发生在你实例化form的时候),这个过程我也不展开了。好吧,不知道有没有解释你
name = form.name.data
为什么会有数据的疑问。
我实在不想在打字了,好累噢!!!!!
好
吧,总结起来就是,HTTP utils将用户的raw request解析成符合wsgi规范的environ,然后flask
instance将environ丢到线程级的request
object里,在你实例化flask.ext.wtf.Form及其子类时,会从request object里解析并映射数据到form中。
关于读书的话,如果你觉得你实在看不明白,那可能是有关web底层一点的知识稍微欠缺,可以补补这块的知识,对于框架的处理机制,最好的办法是 看!!!源!!!!码!!!!!
看不懂就补基础,如此而已。
上面过程都是我信手打出来的,也好久没用flask了,写的时候也没查资料,如有bug或建议可以告诉我,以便我修改。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)