如何处理类层次结构中的python装饰器?

Posted

技术标签:

【中文标题】如何处理类层次结构中的python装饰器?【英文标题】:how to deal with python decorators in a class hierarchy? 【发布时间】:2020-03-29 12:09:55 【问题描述】:

我正在使用DRF 开发一个 Django 项目。我还使用drf-yasg 来记录文档。

长话短说:我正在使用基于类的视图,并且我有一些非常相似的 API,我决定创建一个超类并在其中实现 API 的公共部分!为了更清楚:

class MySuperApiView(APIView):
    permission_classes = [<some permission classes>]

    def uncommon(self):
        pass  # to be override in subclasses

    @swagger_auto_schema(request_body=request_body, responses=api_responses)
    def post(self, *args, **kwargs):
        # do some common stuff here
        self.uncommon()
        # do some other common stuff here

我只是在子类中覆盖 uncommon 方法:

class SomeCustomApi(MySuperApiView):
    def uncommon(self):
        # do specific things here

它工作正常,但我有一个小问题:每个 Api 都有自己的 api_responses,它在超类的 swagger_auto_schema 装饰器中初始化!而且无法更改!

对于这种情况,您有什么建议?我真的很想做OOP并遵守DRY原则。

【问题讨论】:

看起来api_responses 正在作为参数传递给swagger_auto_schema。该值在哪里定义?子类之间会有什么不同? @PatrickHaugh 这是一个dict,每个 API 都必须不同。我将它们声明在视图之外,而您可以看到的api_responsesNone,它已被声明为视图之外。但是,如果可以提供帮助,它可以在里面。我试图在内部声明它并在子类中更改它的值,但它不起作用(因为它不应该) @HamidrezaAhmadi 我认为您的问题可能会在这里得到回答:***.com/questions/42311888/… 他们使用现在已贬值的 django-rest-swagger,但它可能有助于反思。您是否尝试过指定 HTTP 方法? @swagger_auto_schema(method='GET', responses=200: UserSerializer(many=True)) @ThisIsMyName 不!这完全无关紧要。我确实知道如何处理招摇和我正在使用的框架。主要问题在标题中。我正在寻找在 OOP 中处理装饰器的最佳实践。 【参考方案1】:

我终于找到了在 Django 中做这种事情的最佳方法! (所以是的,我不知道如何在其他框架或语言中处理这样的问题!) 我使用名为method_decorator 的类装饰器将swagger_auto_schema 装饰器移动到子类。所以首先我必须导入这个方法:

from django.utils.decorators import method_decorator

然后我像这样改变了超类和子类:

class MySuperApiView(APIView):
    permission_classes = [<some permission classes>]

    def uncommon(self):
        pass  # to be override in subclasses

    # <I removed decorator from here!>
    def post(self, *args, **kwargs):
        # do some common stuff here
        self.uncommon()
        # do some other common stuff here
api_responses =  # responses which belong to "SomeCustomApi"

@method_decorator(name='post',
                  decorator=swagger_auto_schema(request_body=request_body,
                                                responses=api_responses))
class SomeCustomApi(MySuperApiView):
    def uncommon(self):
        # do specific things here

它工作得很好 :) 但是我更喜欢这样的解决方案,我不必重复装饰器,而是只需初始化 responses 参数。如果您在其他语言中遇到此类问题并且您有其他语言的答案,请发布您的答案。

【讨论】:

以上是关于如何处理类层次结构中的python装饰器?的主要内容,如果未能解决你的问题,请参考以下文章

深度学习分类中如何处理类之间的相关性?

在 Swift 中实现数据存储的最佳方法是啥,如何处理类更改

如何使用 ServerManager 从类库中读取 IIS 站点,而不是 IIS express,或者提升的进程如何处理类库?

我应该如何处理 RESTful API 中的对象层次结构?

将两个 python 装饰器合二为一

我应该如何处理@jwt_required 装饰器中引发的异常? (在烧瓶-jwt-扩展中)