Skip to main content
 首页 » 编程设计

python之设计代码以在 Django/Python 应用程序中正确处理错误

2024年09月07日47Renyi-Fan

我正在构建一个 Django 应用程序,我希望就如何正确处理我的代码中的错误和错误获得一些建议。

这是我遇到的问题的一个常见情况示例:用户购买产品。要处理购买,我的 View 需要执行一些操作:

  1. 首先, View 应在数据库中创建一个 User 对象。
  2. 如果成功, View 应创建一个 Order 对象并将其分配给新创建的用户。
  3. 如果成功,我的代码应该创建一个 Product 对象并将其添加到新创建的订单中。

如果没有错误发生,一切都很好 - 但我发现偶尔的错误在我的代码中是不可避免的,我希望我的应用程序能够优雅地处理错误,而不是彻底崩溃。例如,如果出于任何原因无法创建 Order 对象,则 View 应向用户显示错误并删除先前创建的 User 对象。而且,它应该抛出优雅的错误消息,而不是直接崩溃并向用户提供 Http 500 错误。

我能想到的唯一方法是使用一系列极其复杂的嵌套 try/except 子句,如下所示。但是这样设计我的代码非常困惑和耗时,而且感觉不是正确的做事方式。我知道必须有更好的方法来设计 Django 和 Python 中的正确错误处理,但我不太确定它是什么。

对于如何在这种情况下更好地构建我的代码的任何建议,我将不胜感激。

示例代码:

try: 
 
    # Create a new user 
    u = User(email='test@test.com') 
    u.save() 
 
    try: 
 
        # Create a new order 
        o = Order(user=u, name='Order name') 
        o.save() 
 
        try: 
 
            # Create a new product 
            p = Product(order=o, name='Product name') 
            p.save() 
 
        # If a product cannot be created, print an error message and try deleting the user and order that were previously created 
        except: 
 
            messages.add_message(request, messages.ERROR, 'Product could not be created') 
 
            # If deleting the order doesn't work for any reason (for example, o.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
            try: 
                o.delete() 
 
            # I use these 'except: pass' clauses to ensure that if an error occurs, my app doesn't serve a Http 500 error and instead shows the user a graceful error 
            except: 
                pass 
 
            # If deleting the user doesn't work for any reason (for example, u.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
            try: 
                u.delete() 
            except: 
                pass 
 
    # If an order cannot be created, print an error message and try deleting the user that was previously created 
    except: 
        messages.add_message(request, messages.ERROR, 'Order could not be created') 
 
        # If deleting the user doesn't work for any reason (for example, u.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
        try: 
            u.delete() 
        except: 
            pass 
 
# If the user cannot be created, throw an error 
except: 
    messages.add_message(request, messages.ERROR, 'User could not be created') 

请您参考如下方法:

我建议使用 transaction.atomic block ,它应该像这样包含您的模型创建(来自 django 文档的 link):

try: 
    with transaction.atomic(): 
        create_your_objects() 
except IntegrityError: 
    handle_exception() 

这样,在发生任何问题时,上下文管理器中所做的任何更改都将自动回滚。

附言实际上,这就是 django 默认情况下处理每个 View 的方式,但是对于您的情况,您期望它会失败,那么您可以摆脱 500 错误,并且在发生问题的情况下仍然可以获得干净的数据库,而无需删除每个创建的对象。