背景:
使用flask开发的一个web系统,后台用户管理采用的是点击目录后采用load方式不刷新动态加载
1、如图,点击“兖矿集团”,动态加载出右侧的页面
主页面html名称:usermanage.html,代码如下:
{% extends 'base.html' %}
{% block headload %}
{% endblock headload %}
{% block sidebarfunction2 %}
{% endblock sidebarfunction2 %}
{% block sidebarfunction6 %}
{% endblock sidebarfunction6 %}
{% block sidebarfunction7 %}
{% endblock sidebarfunction7 %}
{% block sidebarfunction3 %}
{% endblock sidebarfunction3 %}
{% block sidebarfunction4 %}
系统管理
{% endblock sidebarfunction4 %}
{% block contentheader1 %}
用户管理
{% endblock contentheader1 %}
{% block contentheader2 %}
系统管理用户管理{% endblock contentheader2 %}
{% block content %}
{% endblock content %}
{% block script %}
{{ super() }}
$(function () {
var tempdata = {{ groups | tojson }};
var groups = JSON.parse(tempdata);
$('#treeview-user').treeview({
levels: 1,
color: "#428bca",
showTags: true,
enableLinks: true,
selectable: true,
data: groups,
onNodeSelected: function (event, node) {
// $('div#datashow-adduser').load(url = "{{ url_for('index') }}" + 'system/usermanage_ajax/' + node.id + '/' + node.gid + '/' + node.cid + '/' + node.ccid + '/' + node.mid + '/' + node.ssid + ' #adduser'); //注意#号前的空格
// $('div#datashow-deluser').load(url = "{{ url_for('index') }}" + 'system/usermanage_ajax/' + node.id + '/' + node.gid + '/' + node.cid + '/' + node.ccid + '/' + node.mid + '/' + node.ssid + ' #deluser');
$('div#generaluser').load(url = "{{ url_for('index') }}" + 'system/usermanage_ajax/' + node.id + '/' + node.gid + '/' + node.cid + '/' + node.ccid + '/' + node.mid + '/' + node.ssid);
}
});
});
function changepass() {
window.open("{{ url_for('index') }}" + 'system/usermanage/changepass');
// window.open("http://133dg.com");
}
{% endblock script %}
对应的视图函数:
@app.route('/system/usermanage/')
@login_required
def usermanage():
current_time = datetime.utcnow()
groups = general.Groups()
return render_template('system/usermanage.html', groups=json.dumps(groups), current_time=current_time)
加载的右侧页面名称:usermanage_ajax.html,代码如下:
普通用户添加
当前添加用户权限范围: {{ info.name }}
{% for message in get_flashed_messages() %}
×
{{ message }}
{% endfor %}
{{ form.csrf_token() }}
{{ form.username(class="form-control", placeholder="用户名") }}
{{ form.password(class="form-control", placeholder="密码") }}
{{ form.name(class="form-control", placeholder="姓名") }}
{{ form.sex(class="form-control") }}
{{ form.mobile(class="form-control", placeholder="手机") }}
{{ form.email(class="form-control", placeholder="邮箱") }}{{ form.email.errors[0] }}
{{ form.title(class="form-control", placeholder="职衔") }}
{{ form.telephone(class="form-control", placeholder="座机") }}
{{ form.address(class="form-control", placeholder="地址") }}
{{ form.submit(class="btn btn-primary btn-block", id="btn") }}
普通用户管理
权限范围为{{ info.name }}的已有用户列表:
序号用户名姓名职衔性别手机号邮箱座机地址操作
{% for i in user_list %}
{{ loop.index }}{{ i.username }}{{ i.name }}{{ i.title }}{{ i.sex }}{{ i.mobile }}{{ i.email }}{{ i.telephone }}{{ i.address }}重置密码
删除用户
{% endfor %}
$('#modal1').on('show.bs.modal', function (e) {
//get data-id attribute of the clicked element
var username = $(e.relatedTarget).data('username');
// alert(username);
//populate the textbox
$(e.currentTarget).find('span#username1').text(username);
$(e.currentTarget).find('button#confirm1').attr("onclick", "location.href='{{ url_for('index') }}' + 'system/usermanage/resetpass/" + username + "'" + ";return false;")
});
$('#modal2').on('show.bs.modal', function (e) {
//get data-id attribute of the clicked element
var username = $(e.relatedTarget).data('username');
// alert(username);
//populate the textbox
$(e.currentTarget).find('span#username2').text(username);
$(e.currentTarget).find('button#confirm2').attr("onclick", "location.href='{{ url_for('index') }}' + 'system/usermanage/deluser/" + username + "'" + ";return false;")
});
$(function () {
$('#btn').click(function () {
//ajax提交
post_data = $('#adduserform').serialize();
function show (data, tag) {
if (data.errors.hasOwnProperty(tag)) {
$('span#'+tag).text(data.errors[tag])
// alert(data.errors['username'])
}
else {
$('span#'+tag).text('')
}
}
$.ajax({
url: "{{ url_for('adduser', gid=info.gid, cid=info.cid, ccid=info.ccid, mid=info.mid, ssid=info.ssid) }}",
type: 'POST',
data: post_data,
success: function (data) {
show(data, 'username');
show(data, 'password');
show(data, 'name');
show(data, 'sex');
show(data,'mobile');
show(data,'email');
show(data,'title');
show(data,'telephone');
show(data,'address');
}
});
});
});
function test() {
//ajax提交
post_data = $('#adduserform').serialize();
function show (data, tag) {
if (data.errors.hasOwnProperty(tag)) {
$('span#'+tag).text(data.errors[tag])
// alert(data.errors['username'])
}
else {
$('span#'+tag).text('')
}
}
$.ajax({
url: "{{ url_for('adduser', gid=info.gid, cid=info.cid, ccid=info.ccid, mid=info.mid, ssid=info.ssid) }}",
type: 'POST',
data: post_data,
success: function (data) {
show(data, 'username');
show(data, 'password');
show(data, 'name');
show(data, 'sex');
show(data,'mobile');
show(data,'email');
show(data,'title');
show(data,'telephone');
show(data,'address');
}
});
}
对应的视图函数:
@app.route('/system/usermanage_ajax//')
@login_required
def usermanage_ajax(id, gid, cid, ccid, mid, ssid):
current_time = datetime.utcnow()
info = {}
user_list = []
adduserform = general.AddUserForm()
sql1 = '''select u.gid,u.cid,u.ccid,u.mid,u.ssid,u.username
from users u
where (u.gid={0} or {0} is null)
and (u.cid={1} or {1} is null)
and (u.ccid={2} or {2} is null)
and (u.mid={3} or {3} is null)
and (u.ssid={4} or {4} is null)'''.format(gid, cid, ccid, mid, ssid)
users = general.SQL(sql1)
sql2 = '''select i.groupname,i.companyname1,i.companyname2,i.minename,'该套设备'
from identifier i
where (i.gid={0} or {0} is null)
and (i.cid={1} or {1} is null)
and (i.ccid={2} or {2} is null)
and (i.mid={3} or {3} is null)
and (i.ssid={4} or {4} is null)'''.format(gid, cid, ccid, mid, ssid)
temp = general.SQL(sql2)[0]
info['gid'] = gid
info['cid'] = cid
info['ccid'] = ccid
info['mid'] = mid
info['ssid'] = ssid
if int(id) < 10000:
for user in users:
if not user['cid']:
user_list.append(user)
info['name'] = temp['groupname']
elif 10000 < int(id) < 20000:
for user in users:
if not user['ccid'] and not user['mid']:
user_list.append(user)
info['name'] = temp['groupname'] + '>>' + temp['companyname1']
elif 20000 < int(id) < 30000:
for user in users:
if not user['mid']:
user_list.append(user)
info['name'] = temp['groupname'] + '>>' + temp['companyname1'] + '>>' + temp['companyname2']
elif 30000 < int(id) < 40000:
for user in users:
if not user['ssid']:
user_list.append(user)
if not temp['companyname2']:
info['name'] = temp['groupname'] + '>>' + temp['companyname1'] + '>>' + temp['minename']
else:
info['name'] = temp['groupname'] + '>>' + temp['companyname1'] + '>>' + temp['companyname2'] + '>>' + temp['minename']
elif len(id) == 7:
if not temp['companyname2']:
info['name'] = temp['groupname'] + '>>' + temp['companyname1'] + '>>' + temp['minename'] + '>>' + '该套设备'
else:
info['name'] = temp['groupname'] + '>>' + temp['companyname1'] + '>>' + temp['companyname2'] + '>>' + temp['minename'] + '>>' + '该套设备'
return render_template('system/usermanage_ajax.html', current_time=current_time, info=info, user_list=user_list, form=adduserform)
2、问题
为了实现添加用户表单(adduserform)的表单验证,我使用了wtform,效果如图
这个表单的代码:
class AddUserForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(message='用户名不能为空')])
password = StringField('密码', validators=[DataRequired('用户密码不能为空!'), Length(min=4, message='密码位数要大于4位')])
name = StringField('姓名', validators=[DataRequired('用户姓名不能为空!')])
sex = SelectField(choices=[(1, '男'), (2, '女')], coerce=int)
mobile = StringField('手机', validators=[DataRequired('用户手机不能为空!')])
def validate_mobile(form, field):
if not field.data.isnumeric():
raise StopValidation('手机号只能输入数字')
elif len(str(field.data)) != 11:
raise StopValidation('手机号位数不正确')
email = StringField('邮箱', validators=[DataRequired('用户邮箱不能为空!'), Email('邮箱格式错误!')])
title = StringField('职衔', validators=[DataRequired('用户职衔不能为空!')])
telephone = StringField('座机', validators=[DataRequired('用户座机不能为空!')])
address = StringField('地址', validators=[DataRequired('用户地址不能为空!')])
submit = SubmitField('登录')
adduser视图函数:
@app.route('/system/usermanage/adduser/', methods=['POST'])
@login_required
def adduser(gid, cid, ccid, mid, ssid):
adduserform = general.AddUserForm(request.form)
info = {}
info['gid'] = gid
info['cid'] = cid
info['ccid'] = ccid
info['mid'] = mid
info['ssid'] = ssid
print(adduserform.validate())
if request.method == 'POST':
if adduserform.validate_on_submit():
formdatas = request.form
print('formdatas',formdatas)
password = generate_password_hash(formdatas['password'])
username = formdatas['username'].strip()
if general.SQL('''select username from users where username='{0}' '''.format(username)):
info['type'] = 'warning'
info['title'] = '错误'
info['notice'] = '用户名:' + username + ' 已存在!'
print('用户名:' + username + ' 已存在!')
return render_template('notice.html', info=info)
# flash('用户名:' + username + ' 已存在!')
# errors['flash'] = '用户名:' + username + ' 已存在!'
else:
sql = '''insert into users (gid,cid,ccid,mid,ssid,username,password,type,name,sex,email,mobile,telephone,title,address)
values ({0},{1},{2},{3},{4},'{5}','{6}',{7},'{8}','{9}','{10}','{11}','{12}','{13}','{14}')'''.format(
gid,cid,ccid,mid,ssid,username,password,3,formdatas['name'],formdatas['sex'],formdatas['email'],
formdatas['mobile'],formdatas['title'],formdatas['telephone'],formdatas['address'])
print(sql)
try:
general.SQL(sql)
info['type'] = 'success'
info['title'] = '添加用户成功'
info['notice'] = '用户' + username + ' 已添加!'
print('返回失败?')
return render_template('notice.html', info=info)
except Exception as error:
print(request.path, error)
info['type'] = 'warning'
info['title'] = '错误'
info['notice'] = '出现错误,请联系管理员!'
return render_template('notice.html', info=info)
else:
errors = adduserform.get_errors()
print(errors)
return jsonify({'status':400, 'errors': errors})
else:
pass
为了能在当前页面显示验证的错误信息,在usermanage_ajax.html页面,我使用了ajax,采用post方式提交到adduser视图处理,那么问题来了,本来程序执行到这个地方:
try:
general.SQL(sql)
info['type'] = 'success'
info['title'] = '添加用户成功'
info['notice'] = '用户' + username + ' 已添加!'
print('返回失败?')
return render_template('notice.html', info=info) #执行到这个地方返回了视图
except Exception as error:
print(request.path, error)
info['type'] = 'warning'
info['title'] = '错误'
info['notice'] = '出现错误,请联系管理员!'
return render_template('notice.html', info=info)
应该返回结果的,类似下图的效果
但是,实际上却出现如下的错误:
我大概了解是因为从system/usermanage发起的请求,referer指向的是system/usermanage,所以返回到此,但是因为system/usermanage的视图函数我并没有设置POST方法,所以报了这个错误,我想问的是该怎么处理这个? 以使他能达到我需要的效果(显示notice.html视图,也就是哪个类似的效果)
3、我试过的方法
如果在usermanage_ajax.html中不采用ajax方式post,而是将url写到form的action里,程序执行到这个地方是不会报错的,但是不采用ajax貌似不能在当前页显示验证的错误消息啊
try:
general.SQL(sql)
info['type'] = 'success'
info['title'] = '添加用户成功'
info['notice'] = '用户' + username + ' 已添加!'
print('返回失败?')
return render_template('notice.html', info=info) #执行到这个地方返回了视图
except Exception as error:
print(request.path, error)
info['type'] = 'warning'
info['title'] = '错误'
info['notice'] = '出现错误,请联系管理员!'
return render_template('notice.html', info=info)
4、拜托各位大神帮帮忙,这个问题卡了我3天了,非常感谢。半路出家的程序猿,水平比较渣
总结一下,不要让他出现405错误,能正常返回我的notice视图
5、P.S. 还有一个问题,就是wtforms的验证即使出现了错误,为什么还是能通过提交,难道不是应该停下来等待修正输入吗?
如果是空的,页面不会提交,但是比如邮箱,虽然填了,但是格式不正确,或者手机,位数不正确(我后台已经抓取到了错误),但是页面为什么还是会提交呢?(然后就会显示那个405错误)