Django:将异常从模型传递到视图

0 投票
2 回答
984 浏览
提问于 2025-04-18 04:33

我有一个模型,这个模型里有很多方法,这些方法会调用第三方服务(比如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 个回答

0

为了让代码更清晰,我会在模型里捕捉到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
1

解决这个问题的简单方法就是捕捉异常,然后再抛出一次。这虽然能处理眼前的问题,但并不能解决更大的问题,也就是你的应用程序是如何构建的。

你应该避免把支付逻辑和你的模型紧密耦合;如果明天你需要添加另一个支付提供商,你会发现从模型中提取这些逻辑会非常麻烦。

你应该把支付逻辑放在视图之外。你的支付视图应该只处理金额和支付方式,其他的事情应该单独处理。以下是我建议的做法(非常简化):

  1. 为你的应用程序创建一个围绕Stripe API的包装器。这样将来更换Stripe或添加其他支付提供商会更容易。

  2. 这个包装器应该接受三样东西:

    1. 要支付的金额
    2. 交易的日期和时间
    3. 支付方式(可以默认设置为Stripe)

    然后你的包装器会使用提供商的API发起支付,并返回成功或失败的状态,同时附带提供商返回的任何信息(比如交易参考号等)。

  3. 你的视图会处理交易的结果,如果成功了,就更新你的模型;如果失败了,同样更新模型并相应地重定向用户。

这样你就实现了:

  1. 为你的支付逻辑创建了一个可插拔的架构。
  2. 把与模型无关的逻辑移出了模型。
  3. 让你的视图成为支付流程的“控制器”。

撰写回答