Front Python

用Django和Backbone.js生成表单

Django带了Forms框架,但如果不用Model Form,就要把在Model中定义的字段再写一遍。而且现在项目中都会用到前端工具包/框架,比如Bootstrap,于是as_table/as_ul/as_p就不能直接用了,每个字段都要手动写到HTML里。我之前是用django-crispy-forms这个模块来简化。

Backbone.js是一个基础框架,没有生成表单的功能,但有一个依赖于Backbone.js,很好用的Forms框架—— backbone-forms

django-crispy-forms和backbone-forms做的事非常相近(至少render出的结果是一样的),没必要同时使用。理想的方案是Django搭配backbone-forms,后者从Django定义的Model/Object中获得Schema,生成表单。目前代码是跑通了,但比较折腾,是用Python的JS解析器,引入需要的JS库,执行从Django Model生成的JS代码,最后返回Form的HTML代码到前端。有些步骤还需要改进。这篇文章先分享:从Django的Model生成JS代码,传到前台,生成表单的方法。

Install

在html模板中引入需要的JS库(引用的都是在线的库,可能会出现无法访问的情况),bootstrap.js会自动给表单添加上Bootstrap的样式,要在backbone-forms.min.js后引入。在DOM之后加入script标签,之后得到一个Customer的object,在script标签内调用render_form方法,生成JS代码。

Model & View & Template

例如有一个名为Customer的Model,给它添加render_form的方法:

  • line 19: 定义Django Model Field与backbone-form Schema Type的对应关系,例如CharField/TextField对应Text和TextArea,Big/Small*IntegerField/PositiveIntegerField都是对应Number类型;
  • line 27~31: 对字段进行for操作,id字段不做处理。如果字段中设置了choices,就用Select来处理;
  • line 32: 生成JS代码。这里是把实例化Backbone.Form的工作也放在后端完成了。

views.py部分的代码看具体应用场景,得到object后,在模板中调用render_form方法,实际生成的表单如下图:

Validation & Fill

以上是完成了Django Form生成的工作,接下来用backbone-form来实现表单的验证,以及初始化数据的功能。

首先是验证,Django Model的字段,默认是必须填写,backbone-form中的字段默认可以为空,所以要把render_form方法做如下改动:

line 11~12:进行判断,如果field.blank不为True(model没有设置blank=True),就在JS代码中加上required的验证。当更新Backbone.js Model时(form.commit),如果required的字段没有填写会报错:

然后是初始化数据,这要用到Backbone.js的Model功能。代码中保持了Django Model的命名和Backbone.js Model的命名一致,把object的数据在Backbone.js Model实例化时传进去:

方法名是render_fill_form,以便和不初始化数据的render_form区分。Django模板不支持直接传递函数,没办法写在一个函数里,除非换其他模板引擎。也可以做成templatetags,只是代码量会增多,自由度也小了。

Afterword

以上是用backbone-form代替Django Forms的方法,节约了不少开发时间,render_(fill_)form函数比较灵活,对于大多数Django Model只要复制上去就能用。这样改动也更合理一些,毕竟作为一个后端框架,表单相关的操作本来就不适合它。类似字段是否为空、数据格式是否合法的校验,就应该是前端来完成的。

Leave a Reply

Your email address will not be published. Required fields are marked *