Flask 利用AJAX异步实现二级(甚至多级)下拉表单级联 --记录那些坑

首先我是用的WTForms生成的表单,我也用input标签写过,感觉不整洁,就弃用了,这里我以学院school、系department、团队team,这三级关系做介绍。(和省,市,区一样)
下面的Form类的定义(数据库定义就不给出了,这里使用SQLalchemy查询语言):

class RegisterForm(FlaskForm):
#注意这样定义school就是表单id,下面也一样
    school = SelectField('学院', coerce=int, default='xxx')
    department = SelectField('系', coerce=int, default='xxx')
    team = SelectField('团队', coerce=int, default='xxx')
    #初始化下拉表单值,直接给出了学院的所有值
        def __init__(self, *args, **kwargs):
	        super(RegisterForm, self).__init__(*args, **kwargs)
	        #第一个值给空是防止第一个选择就是想要的,下拉表单感受不到变化
	         self.school.choices=[(1,'')]
       		 for school in School.query.order_by(School.id).all():
           	 	self.school.choices.append((school.id,school.name))
        	self.department.choices = [(1,'')]
        	for department in Department.query.order_by(Department.id).all():
            	self.department.choices.append((department.id,department.name))
        	self.team.choices = [(1,'')]
        	for team in Team.query.order_by(Team.id).all():
            	self.team.choices.append((team.id,team.name))

那么前端表单生成如下(别忘了CSRF验证)

{{ form.csrf_token }}
{{ render_field(form.school,onchange="Select('school','#department',school_url,csrf)") }}
{{render_field(form.department,onchange="Select('department','#team',department_url,csrf)")}}
 {{ render_field(form.team) }}

当然,onchange就是JavaScript检测下拉表单值发生变化的函数,这个检测肯定是实时的,只要表单值改变,那么就会触发JS函数Select(),那么我传的这些参数是什么意思呢,可以先看下面的js程序。

function Select(choose,id,register_url,csrf) {
        var data;
        var csrftoken = csrf;
        var select = document.getElementById(choose);
        $(id).html("");       //每次重新选择当前列表框,就清空下一级列表框。
        for (i=0;i").appendTo(id);
                            for (i=0;i" + data[i] + "").appendTo(id)//将后端返回的数据逐项插入到下一级列表框中
                            }
                        }
                        else {
                            alert('error');
                        }
                    }
                });
            }
        }
    }

那么应该可以猜到:

第1个参数choose是指当前选择变化的表单id
第2个参数id是指下一级表单的id,如choose是某个学院id,那么id应该传入系表单的id.
第3个参数register_url是指AJAX需要的参数url->后端视图函数路经
第4个参数csrf是ajax的表单验证参数(最坑,明明我已经有验证表单了)
那么这些参数怎么获取的
在根路经base.html



那么接下来就是后端对AJAX的处理了,这个是选择学院后下级表单自动跳出对应系

@auth_bp.route('/selectschool/register',methods=['GET','POST'])
def SelectSchool():
    if request.method == 'POST':
        data = request.get_json()
        name = data['name']
        school = School.query.filter_by(name = name).first()
        departments = [(department.id,department.name) for department in Department.query.filter_by(school_id = school.id).all()]
        return jsonify(departments)

选择系后自动跳出团队和上面一样就不多说了。
当然这些操作都可以用一个视图函数处理,只需js多传入一个判断是哪个表单发生了改变的值,在data字典里添加一个键值对即可。
按这种思路多少级关系都没问题(前提是你数据库设计好这些关系)

做个记录,共勉,虽然内容不算完美
还有就是post提交方式,一般后端用request.form.get()获取数据
get方式,一般用request.args.get()获取数据
我这是AJAX发送JSON数据,所以获取数据不一样,
获取数据一定要考虑会不会为None。

你可能感兴趣的:(Flask,Web)