上下文管理器可以保持Django视图的整洁?

时间:2019-06-11 07:02:24

标签: django django-rest-framework

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

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)

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

2 个答案:

答案 0 :(得分:2)

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

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

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

但是,正如您提到的那样,您正在使用Django rest框架,对我来说,这对Serializers并使用其验证系统似乎是一个很好的用法。当然,假设您的get_data_from_somewhere1使用request数据作为输入(至少部分)。 要调用序列化程序验证,您可以调用is_valid,例如

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

然后在序列化程序的validate函数中,使用所需的状态代码(例如, ValidationError('my error msg')(来自rest_framework.exceptions)。

或者您可以从ValidationError函数中提高status_code(或扩展它以覆盖其默认validate_data())。

答案 1 :(得分:0)

在我看来,这是对上下文管理器的不当使用,因为它没有提供任何真实的上下文。通常,上下文管理器会提供一些上下文,例如数据库连接或文件句柄,这需要在进入和退出上下文(例如打开和关闭数据库连接)时完成工作。

为什么不只是将验证逻辑放在常规函数中?

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

然后做

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

在您看来,您知道执行逻辑时已验证数据。