这篇文章总结了控制表单样式的几种方式和常见的问题。
使用Flask-WTF
在表单类里控制样式
我们可以在表单类里传入一个字典(render_kw),把需要添加到字段的属性以键值对的形式写进去,像这样:
body = TextAreaField(u'正文', validators=[Required(u'内容不能为空!')],
render_kw={'class': 'text-body', 'rows': 20, 'placeholder': u'你有什么想法?'})
在HTML里渲染表单:
...
{{ form.body }}
...
渲染的结果:
<textarea class="text-body" id="body" name="body" placeholder="你有什么想法?" rows="20"></textarea>
注意事项:字段名将被作为id的值,这可能会和你定义的其他同名元素冲突。
在渲染时控制样式
我们也可以在渲染时传入字段的属性(不使用render_kw),类似这样:
...
{{ form.body(class_="text-body", rows="20", placeholder="你有什么想法?") }}
...
渲染后的结果和上面一样。
render_kw在WTForms 2.1及以上版本适用。
使用Flask-Bootstrap
使用Flask-Bootstrap提供的表单函数来渲染表单时,也可以像上面那样在表单类或是渲染函数里传入字段的属性:
...
{{ wtf.form_field(form.body, class_="text-body") }}
...
这里需要先导入Flask-Bootstrap提供的表单模板,另外完整的表单形式见Flask表单系列第一篇文章
这里需要注意的是,Flask-Bootstrap会给表单所有字段添加一个form-control来控制样式,这时你再通过render_kw传入已经被定义的属性(class)会失败。如果要传入指定的类,可以在渲染时传入并且增加form-control类:
...
{{ wtf.form_field(form.body, class_="form-control text-body") }}
...
或是:
...
{{ form.body(class_="form-control text-body") }}
...
在一些文档里,推荐使用class_=’ ‘的方式来传入类,因为class是Python的保留关键字。
小技巧:在输入框里添加图标
有一些网站会在表单左侧放一个图标来增加交互性,比如这样:
如果是普通的表单,那么使用Bootstrap提供的表单验证状态类,可以很容易的实现,但是使用Wtforms渲染表单却没法实现。我们可以这样解决:
在CSS里定义一个类,将glyphicon图标的base64数据作为背景图片:
.user-icon {
padding-left:30px;
background-repeat: no-repeat;
background-position-x: 4px;
background-position-y: 4px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAYAAAArdgcFAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjY1RTYzOTA2ODZDRjExREJBNkUyRDg4N0NFQUNCNDA3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIzOUVGMUYxMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIzOUVGMUYwMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMTgwMTE3NDA3MjA2ODExODA4M0ZFMkJBM0M1RUU2NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowNjgwMTE3NDA3MjA2ODExODA4M0U3NkRBMDNEMDVDMSIvPiA8ZGM6dGl0bGU+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPmdseXBoaWNvbnM8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkX/peQAAACrSURBVHja7JSLCYAwDEQbJ3AER+kouoFu0FEcqSM4gk4QE4ggVRPxg1A8OFCSvkqC5xDRaSZ5ciTjyvzuzbMnwKjY34FHAx618yCQXQHAcVFE5+GoVijgyt3UN1/+hPKFd0a9ubxQa6naMjOdOY2jJAdjZIH7tJ8gzRNuZuho5MriUfpLNbhINXk4Cd27pN3AJVqvQlMPSxSz+oegqXuQhz9bNvDpJfY0CzAA6Ncngv5RALIAAAAASUVORK5CYII=);
}
然后在模板里渲染时传入这个类:
<form method="POST">
{{ form.hidden_tag() }}
{{ wtf.form_field(form.username, class_="form-control user-icon") }}
{{ wtf.form_field(form.password) }}
{{ wtf.form_field(form.submit) }}
</form>
图标(glyphicon)的base64数据可以在这个网站上可以获取到。
另外,也可以使用一个小图片(25*25大小较合适)来代替base64数据,像这样:
background-image: url({{ url_for('static', filename='user.png') }});
相关链接
- http://wtforms.readthedocs.io/en/latest/fields.html#the-field-base-class
- http://stackoverflow.com/questions/39520899/flask-wtf-forms-adding-a-glyphicon-in-a-form-field
– – – – –
更多关于Flask和Web开发的优质原创内容,欢迎关注Hello, Flask! – 知乎专栏。