以前无刷很火,现在又回到http协议本身,html也到了第五个版本,用flask也有了好些个年头。
flask用的人很多,可惜很多企业并不开源,像豆瓣这样公开架构的还是很有限,开源的东西里不是什么都是开源的,比如很多最佳实践都是散落在很多博客中。有的最佳实践只是做到了一部分,一个完整的最佳实践到现在才自己比较满意。没办法,越是灵活的东西也就意味着无限的可能性,更别说flask这种牛逼的微框架了。
在开始前请确认你了解wtform并且已经会使用它。用过才知道它的强大和灵活。但是一直没有好好的研究出怎么无缝的使用它和ajax。主要需要实现如下的几个目标:
- 无刷,呵呵,必须的;
- view只有一个method,能够同时实现新建、编辑、保存,因为wtform就能很好的支持,所以做不到不算最佳;
- template只有一个,模板最烦,重复展现最恶心,所以如何最大化重用是必须要考虑的,能省下很多work hour;
大概的思路是先get加载新建的表单,ajax提交表单数据,返回status为ok则表明添加成功,否则返回html(这时的form已经包含了字段的错误信息)
下面是展示例的代码
<pre> <form role="form" method="POST" class="form-horizontal {{ 'new-enterprise' if is_new }} enterprise-info" action="{{ url_for('enterprise_save_page',id=enterprise.id) }}" id="enterprise_form"> <div class="modal-header"> <h5 class="modal-title">{{ '添加企业' if is_new }}</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <fieldset> {{ enterprise_form.hidden_tag() }} {{ render_field(enterprise_form.name) }} {{ render_select(enterprise_form.industry) }} </fieldset> </div> <div class="modal-footer"> <button type="submit" class="btn btn-modal-back" data-dismiss="modal" id="confirm_cancel">取消 </button> <button type="button" class="btn btn-modal-confirm" data-dismiss="modal" id="confirm_ok">确认 </button> </div> </form> </pre>
// add step button opens modal containing step form loaded via ajax $('#btn_add_enterprise').click(function () { var url = "{{ url_for('enterprise_save_page',id=None) }}"; $.get(url, function (data) { $('#enterprise_info_modal .modal-content').html(data); $('#enterprise_info_modal').modal({ keyboard: false, show: true }); $('#confirm_ok ').click(function (event) { event.preventDefault(); $.post('{{ url_for('enterprise_save_page',id=0) }}', data = $('#enterprise_form').serialize(), function (data) { if (data.status == 'ok') { $('#enterprise_info_modal').modal('hide'); alert('新企业已添加'); location.reload(); } else { $('#enterprise_info_modal .modal-content').html(data); $('#enterprise_info_modal').modal({ keyboard: false, show: true }); } }); }) }); });
@app.route('/admin/enterprise/new', methods=['GET'], defaults={'id': None}) @app.route('/admin/enterprise/save/<int:id>', methods=['POST', 'GET']) @admin_required() def enterprise_save_page(id): if id is not None and id > 0: enterprise = EnterpriseInfo.query.get(id) else: enterprise = EnterpriseInfo() enterprise_form = EnterpriseInfoForm(obj=enterprise) if enterprise_form.validate_on_submit(): if id == 0: enterprise.id = None db.session.add(enterprise) db.session.commit() return jsonify(status='ok') args = locals() return render_template('admin/enterprise/_info.html', **args)