Django:将异常从模型传递到视图
我有一个模型,这个模型里有很多方法,这些方法会调用第三方服务(比如Stripe),而这些调用可能会出错。
在模型里,我处理这些错误:
class Plan(models.Model):
def update():
try:
// get the customer data related to id "xyz"
except StipeError as error_obj:
return error_message
在视图中,我会在Plan
实例上调用上面的方法。
我更倾向于在视图中使用try-catch来处理错误,但不想在这里捕获StripeError
,因为这个错误会在模型里被捕获。所以我想在模型里处理错误,同时在视图中这样做:
def plan_view(request):
.....
try:
plan.update()
except:
//redirect with exception message
一种方法是在视图中放一个try-catch块来处理StripeError
,但我觉得这样做不太合适,因为错误的根源在模型的方法里,而不是在视图中。
那么,我该如何在模型里处理错误,同时还能在视图中根据这个错误进行重定向呢?
2 个回答
为了让代码更清晰,我会在模型里捕捉到StipeError这个错误,然后再抛出一个合适的异常,这样plan_view(..)就可以捕捉到这个异常。这样一来,视图就不需要知道模型内部发生了什么复杂的事情。
class Plan(models.Model):
def update():
try:
// get the customer data related to id "xyz"
except StipeError as error_obj:
raise UpdateException() # define the exception outside of the model
....
def plan_view(request):
.....
try:
plan.update()
except UpdateException:
//redirect with exception message
解决这个问题的简单方法就是捕捉异常,然后再抛出一次。这虽然能处理眼前的问题,但并不能解决更大的问题,也就是你的应用程序是如何构建的。
你应该避免把支付逻辑和你的模型紧密耦合;如果明天你需要添加另一个支付提供商,你会发现从模型中提取这些逻辑会非常麻烦。
你应该把支付逻辑放在视图之外。你的支付视图应该只处理金额和支付方式,其他的事情应该单独处理。以下是我建议的做法(非常简化):
为你的应用程序创建一个围绕Stripe API的包装器。这样将来更换Stripe或添加其他支付提供商会更容易。
这个包装器应该接受三样东西:
- 要支付的金额
- 交易的日期和时间
- 支付方式(可以默认设置为Stripe)
然后你的包装器会使用提供商的API发起支付,并返回成功或失败的状态,同时附带提供商返回的任何信息(比如交易参考号等)。
你的视图会处理交易的结果,如果成功了,就更新你的模型;如果失败了,同样更新模型并相应地重定向用户。
这样你就实现了:
- 为你的支付逻辑创建了一个可插拔的架构。
- 把与模型无关的逻辑移出了模型。
- 让你的视图成为支付流程的“控制器”。