我正在尝试创建一个表单来编辑用户帐户。 此代码适用于已存在的用户。
如您所见,我在try / catch之前输入了一个return语句。 当用户名已存在时,这将生成预期的完整性异常。
但是如果我将其注释掉并让它进入try / catch块,则不会产生异常,它只是重定向到HTTPFound而没有错误。 对冲洗的呼吁没有任何作用。
if form.validate():
user.username = form.username.data
if form.password.data != "":
user.password = encrypt(form.password.data)
user.is_active = form.is_active.data
user.email = form.email.data
user.groups = form.groups.data
# if i return here i will get integrity error as expected
#return HTTPFound(location=request.route_url('user_details', id=user.id))
with transaction.manager as tx:
try:
request.sqldb.flush()
# no exception is generated here
return HTTPFound(location=request.route_url('user_details', id=user.id))
except IntegrityError as e:
tx.abort()
if 'UNIQUE constraint failed: users.username' in str(e):
form.username.errors.append('Username already exists')
else:
errors.append('Integrity Error')
修改 这是有效的代码 事务管理器部分甚至不需要:
user.username = form.username.data
if form.password.data != "":
user.password = encrypt(form.password.data)
user.is_active = form.is_active.data
user.email = form.email.data
user.groups = form.groups.data
try:
request.sqldb.flush()
return HTTPFound(location=request.route_url('user_details', id=user.id))
except IntegrityError as e:
if '(IntegrityError) duplicate key value' in str(e):
errors.append('Username already exists')
else:
errors.append('Integrity Error')
request.sqldb.rollback()
答案 0 :(得分:0)
您需要获取模型,并对事务管理器中的模型对象进行更改,否则会话flush()
的范围有限。 SQLAlchemy足够聪明,可以尝试仅刷新上下文管理器中发生的更改子集。因此:
with transaction.manager as tx:
try:
user = .... # get the user
user.username = form.username.data
if form.password.data != "":
user.password = encrypt(form.password.data)
user.is_active = form.is_active.data
user.email = form.email.data
user.groups = form.groups.data
request.sqldb.flush()
# no exception is generated here
return HTTPFound(location=request.route_url('user_details', id=user.id))
except IntegrityError as e:
tx.abort()
if 'UNIQUE constraint failed: users.username' in str(e):
form.username.errors.append('Username already exists')
else:
errors.append('Integrity Error')
答案 1 :(得分:0)
我的解决方案基于全局异常处理。
http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/pylons/exceptions.html
from pyramid.view as view
import sqlalchemy.exc
@view.view_config(context=sqlalchemy.exc.IntegrityError, renderer='json')
def integrity_error(exc, request):
request.response.status_code = 400
return {
'error': exc.orig.args[1]
}
或
@view.exception_view_config(sqlalchemy.exc.IntegrityError, renderer='json')
def integrity_error(exc, request):
request.response.status_code = 400
return {
'error': exc.orig.args[1]
}
差异在http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/views.html
中描述通过这种方式,我可以从金字塔中获得RESTful Api。它很粗糙,但在快速原型设计中很有用,并且可以在路径中节省大量代码。