首页 > 解决方案 > 保持 Django 视图干净的上下文管理器?

问题描述

我已经问过类似的问题,但这太宽泛了,不是 Django 特有的。使用上下文管理器保持 Django 视图清洁以使代码干燥是一种好习惯吗?这是代码示例(有点伪代码):

class DjangoViewset():
    @action(method=['GET'])
    def custom_action1(request):
        a = get_data_from_somewhere1()
        b = get_data_from_somewhere2()
        if a<b:
            raise 400
        if a==1:
            raise 404
        if a==2:
            raise 403 
        result = some_complicated_logic(a, b)
        return Response(result)

    @action(method=['GET'])
    def custom_action2(request):
        a = get_data_from_somewhere1()
        b = get_data_from_somewhere2()
        if a<b:
            raise 400
        if a==1:
            raise 404
        if a==2:
            raise 403
        result = some_complicated_logic_another(a, b)
        return Response(result)

我可以用这样的东西重构它,还是使用上下文管理器不好?

@contextmanager
def validate_data(a, b):
    if a<b:
        raise 400
    if a==1:
       raise 404
    if a==2:
       raise 403
   yield

class DjangoViewset():
    @action(method=['GET'])
    def custom_action1(request):
        a = get_data_from_somewhere1()
        b = get_data_from_somewhere2()
        with validate_data(a, b):
            result = some_complicated_logic(a, b)
        return Response(result)

    @action(method=['GET'])
    def custom_action2(request):
        a = get_data_from_somewhere1()
        b = get_data_from_somewhere2()
        with validate_data(a, b):
            result = some_complicated_logic_another(a, b)
        return Response(result)

有了这个重构代码看起来就简单多了,但是如果我可以用这种方式使用上下文管理器,我找不到信息,但这不是禁止的风格吗?

标签: djangodjango-rest-framework

解决方案


我不明白为什么要为此目的使用上下文管理器-在这里使用它们不会获得任何好处。只需调用

validate_data(a, b):
result = some_complicated_logic_another(a, b)

validate_data应该足够了,必要时依靠引发错误。

但是既然你提到了,你正在使用 Django rest 框架,对我来说这似乎对序列化器和使用它们的验证系统很有用。当然,假设您get_data_from_somewhere1使用request数据作为输入(至少部分)。要调用序列化程序验证,您可以调用is_valid,例如

serializer = MySerializer(data=request.data, context=...)
serializer.is_valid(raise_exception=True)

然后在序列化程序的validate函数中,使用所需的状态代码引发适当的异常,例如ValidationError('my error msg')(from rest_framework.exceptions)。

或者您可以简单地从您的函数中提升ValidationError(或扩展它以覆盖其默认值status_code,如果需要) 。validate_data()


推荐阅读