在另一个视图函数中包含一个带有渲染的函数

时间:2021-04-13 14:14:49

标签: python django error-handling django-views

想在view中设计一个错误处理函数,在view中的不同main函数中使用。 此错误处理程序函数将收集所需的错误信息,将错误记录到系统中,并将这些信息呈现给错误处理程序页面。

view.py 中的代码如下:

def error_manage(request, error_title, error_detail):
    error_time = datetime.now()
    info_table = {'error_title': error_title,
                     'error_detail': error_detail,
                     'error_time ': error_time ,
                     }
    logger.error(str(error_detail))
    return render(request,'home/error_manage.html', {'error_title': error_title, 
                                                     'info_table ': display_table})


def my_page_1(request):
    try:
        var1 = my_calculation_func()
    except Exception as ex:
        error_manage(request, "Unexpected Error Happened.", ex)
    
    var2 = my_calculation_func2()
    var3 = my_calculation_func3()
    return render(request,'home/my_page_1.html', {'var1': var1 ,'var2': var2 ,'var3': var3})

这里的问题是,当var1发生错误时,程序会跳转到error_manage,但不会在这个函数的返回中停止,也不会成功渲染到error_manage.html中。

它稍后会跳出这个函数并继续运行 var2 和 var3,直到遇到 my_page_1() 中的最终返回。

我知道我可以简单地将 error_manage 中的 return 语句放在 Exception 下的 my_page_1 中。 但是这个错误处理程序会在view.py中的许多其他函数中使用,我不想一遍又一遍地重复。

这个问题有没有好的解决办法?谢谢。

2 个答案:

答案 0 :(得分:3)

以下是装饰器方法的示例:

class MyError(Exception):
    pass


def error_handler(func):
    def decorated(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except MyError as e:
            return f"Oh no! {e} happened!"
    return decorated


@error_handler
def my_view(request):
    if "error" in request:
        raise MyError("request was rubbish")
    return "Great success!"


for r in ["Fine", "no problem", "An error happened"]:
    print(my_view(r))

所以运行这个,我们得到

Great success!
Great success!
Oh no! request was rubbish happened!

所以本质上我们使用装饰器来捕获和处理 MyError 异常,其他异常将不会被处理,而是会像往常一样从视图中冒出来,由 django 的 [默认] 视图错误处理来处理。

答案 1 :(得分:2)

您应该制作一个自定义中间件来处理异常。见Writing your own middleware [Django docs]

class MyMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response
    
    def process_exception(request, exception):
        error_time = datetime.now()
        info_table = {
            'error_detail': exception,
            'error_time ': error_time ,
        }
        logger.error(str(exception))
        return render(request,'home/error_manage.html', {'info_table ': display_table})

现在您需要将此中间件添加到设置中的 MIDDLEWARE 列表中:

MIDDLEWARE = [
    # Default middlewares
    'path.to.MyMiddleware',
]

现在在您看来,您不应该捕获异常并让中间件处理它。

<块引用>

注意:通过这种方式,您传递 error_title 的方法将不起作用,但如果您 需要一些自定义:raise Exception("Unexpected Error Happened.") from ex