踩坑代码:
class registerTo:
def POST(self):
i = web.input()
ident = db.query("select * from users where username = $u", vars=dict(u=i.username))
if i.username == ident[0].username:
return render.register_error1()
if i.password != i.checkpassword:
return render.register_error2()
else:
n = db.insert('users', username=i.username, password=i.password)
raise web.seeother('/login')
(一)
注册校验肯定要涉及到数据库查询,由于我使用的是框架最新的0.61版本,而官方的cookbook仍长期处于0.3版本,部分代码变动较大,我只能阅读源码来掌握最新的使用方法。
ident = db.query("select * from users where username = $u", vars=dict(u=i.username))
如果是0.3版本,以上查询写法会像这样:
支持格式化字符串。
ident = db.query("select * from users where username = %s" % i.username)
但是0.61版本对db.query()方法做了大幅度修改,首先给定参数就发生了很大变化 :
def query(self, sql_query, vars=None, processed=False, _test=False):
其中,第二个参数sql_query是查询语句,如果想对变量传值,得在变量前面加上符号$,如上面的$u;第三个参数vars用来传值,它必须是一个字典,如上所示,你可以写成vars=dict(u=i.username),或者是vars={‘u’: i.username};第四个参数默认为processed=False,只是用来将前两个参数组合成完整的查询语句;第五个参数默认为_test=False,表示返回查询后的结果,如果修改为_test=True,最后只会返回SQLQuery查询语句字符串。因此一般情况下,后两个参数保持默认即可。
对于查询结果集,先用数组下标方式索引到需要的第几个结果(按数据在数据表里存储的顺序,如果存在的话),然后再直接.需要的字段,如上面的ident[0].username,而在0.3版本,如果username在数据表里是第二个字段,那么获取方式为ident[0][1]。
(二)
然后是数据校验
if i.username == ident[0].username:
return render.register_error1()
elif i.password != i.checkpassword:
return render.register_error2()
else:
n = db.insert('users', username=i.username, password=i.password)
raise web.seeother('/login')
对于以上if-else语句,先校验用户名是否存在,然后校验确认密码是否与密码相同,一切都没问题,就注册成功,数据插入用户表。
但假如此时注册时,用户名是新的,但是确认密码与密码不一样,服务器会报错。
实际上是因为此时查询的结果本就为空,代码首先校验的是用户名,根本不存在索引,因此ident[0]直接越界了!
第一个想到的解决办法是,将两部分代码交换位置,即:
if i.password != i.checkpassword:
return render.register_error2()
if i.username == ident[0].username:
return render.register_error1()
但我希望的是,当用户名已存在且确认密码不一样时,优先告诉注册者用户已存在的错误,因此我想到使用try-except的代码块来进行错误处理,即:
try:
if i.username == ident[0].username:
return render.register_error1()
except:
if i.password != i.checkpassword:
return render.register_error2()
else:
n = db.insert('users', username=i.username, password=i.password)
raise web.seeother('/login')
这样就没问题了^^