首先我是用的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 = [(school.id,school.name)
for school in School.query.order_by(School.name).all()]
self.department.choices = []
self.team.choices = []
那麼前端表單生成如下(別忘了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<select.length;i++){
if (select[i].selected){ //判斷被選中項
Name = select[i].text;
data ={
"name":Name
};
$.ajax({ //發起ajax請求
url:register_url,
//加上csrf驗證頭,也可直接加在data裏最前面
headers: {"X-CSRFToken": csrftoken },
type:"POST",
data:JSON.stringify(data),
contentType:"application/json; charset=UTF-8",
success:function (data) { //後端返回數據,是列表形式的
if (data){
for (i=0;i<data.length;i++){
$("<option value='"+data[i]+"'>" + data[i] + "</option>").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中
<script type="text/javascript" >
var school_url = "{{ url_for('auth.SelectSchool') }}";
var department_url = "{{ url_for('auth.SelectDepartment') }}";
var csrf = "{{ csrf_token() }}";
</script>
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}" charset="UTF-8"></script>
那麼接下來就是後端對AJAX的處理了,這個是選擇學院後下級表單自動跳出對應系
@auth_bp.route('/selectschool/register',methods=['GET','POST'])
def SelectSchool():
if request.method == 'POST':
data = request.get_json()
name = data['name']
#這裏我給了[''],而不是[],是避免第一個就是我要選擇的,從而界面感受不到下拉表單變化,不是太懂的話可以用[]試試
DepartmentName = ['']
school = School.query.filter_by(name = name).first()
departments = Department.query.filter_by(school_id = school.id).all()
for department in departments:
DepartmentName.append(department.name)
return jsonify(DepartmentName)
選擇系後自動跳出團隊和上面一樣就不多說了。
當然這些操作都可以用一個視圖函數處理,只需js多傳入一個判斷是哪個表單發生了改變的值,在data字典裏添加一個鍵值對即可。
按這種思路多少級關係都沒問題(前提是你數據庫設計好這些關係)
做個記錄,共勉,雖然內容不算完美
還有就是post提交方式,一般後端用request.form.get()獲取數據
get方式,一般用request.args.get()獲取數據
我這是AJAX發送JSON數據,所以獲取數據不一樣,
獲取數據一定要考慮會不會爲None。