如何传递参数来修改接受带参数函数的装饰器

时间:2021-05-04 22:50:47

标签: python python-3.x django functional-programming python-decorators

我必须创建一个带有参数的装饰器,并使用这些参数来修改一个也带有参数的函数。这是一个关于如何使用带有附加参数的参数装饰任何函数的一般问题,但对于我的特定情况,我需要它用于 Django RQ,以根据环境变量确定是否使用通过装饰器激活的异步队列。

Django RQ 中有一个名为 django_rq.job 的函数,我像这样使用它(它需要 argskwargs):

@django_rq.job('default', timeout=3600, result_ttl=86400)
def upload_missing_documents_s3(batches, projects, uuid_val):
   pass

# A simpler example:
@django_rq.job('default', timeout=3600, result_ttl=86400)
def sample(content):
    file = open("temp/sample.txt", "w+")
    file.write(content)
    file.close()

我本质上需要创建一个装饰器,它接受一个布尔值并返回修改后的函数(有作业)或未修改的函数(没有作业)。但我似乎无法弄清楚,因为有两组参数。我试过这样的事情:

#My attempt, I don't think it works...
def conditional_django_job(function_name, *args, **kwargs):
    if settings.NO_QUEUE:
        return function_name
    else:
        return django_rq.job("default", None, *args, **kwargs)(function_name)

@conditional_django_job('default', timeout=3600, result_ttl=86400)
def sample(content):
    file = open("temp/sample.txt", "w+")
    file.write(content)
    file.close()

我也尝试过使用内部函数,但似乎无法正确使用。如何使用装饰函数的参数实现装饰器?

我尝试查看这个 SO question,但它似乎没有装饰器和函数都有参数的示例:How to make function decorators and chain them together?

谢谢!

1 个答案:

答案 0 :(得分:0)

嗯,我想我过了一段时间才明白。写出一个问题可以帮助回答这个问题,真是太疯狂了。

我认为这是解决方案:

def conditional_django_job(*args, **kwargs):
    def real_decorator(func):
        try:
            if settings.NO_QUEUE:
                print("Returning ordinary func")
                return func
            else:
                print("Returning queued func")
                return django_rq.job(*args, **kwargs)(func)
        except:
            print("Put NO_QUEUE boolean in env variable. Returning ordinary func")
            return func
    return real_decorator