简体   繁体   English

使用django在芹菜中传递User对象

[英]Passing User object in celery using django

I'm currently editing the save method in one of my models, so that I can save who changed an object or created a new one. 我正在编辑我的一个模型中的save方法,这样我就可以保存更改对象或创建新对象的人。

Currently, its working fine when its ran in the main thread, but the save method is also used in different tasks through Celery. 目前,它在主线程中运行时工作正常,但是save方法也通过Celery用于不同的任务。 And when the save method is ran in a task get user returns None . 当在任务中运行save方法时, get user返回None To get a user i'm currently using django-curser since this model is being used in different apps inside my Django project. 为了得到一个用户我正在使用django-curser,因为这个模型正在我的Django项目中的不同应用程序中使用。

Is there a way to send the current user to celery? 有没有办法将当前用户发送到芹菜? I've been told to use a context manager or a wrapper but im not sure how. 我被告知使用上下文管理器或包装器,但我不知道如何。

My save method is: 我的保存方法是:

    def save(self, *args, **kwargs):
        from models import Log
        log_entry = Log()
        log_entry.object_id = self.id
        log_entry.object_repr = self
        user = CuserMiddleware.get_user()
        log_entry.user = user
        log_entry.content_type_id = ContentType.objects.get_for_model(self).id
        log_entry.save()

Thanks. 谢谢。

Solution with decorator: 装饰解决方案:

I think you can use this decorator to add user in celery task 我想你可以使用这个装饰器在celery任务中添加用户

from functools import wraps


def append_user(func):
    @wraps(func)
    def __wrapper__(*args, **kwargs):
        user_login = kwargs.pop('user_login')
        CuserMiddleware.set_user(user_login)
        return func(*args, **kwargs)
    return __wrapper__

And apply it to task this way 并以这种方式应用于任务

@task
@append_user
def celery_job():
    pass

Also for my celery task I use this decorator (to turn off all async jobs in settings) 同样对于我的芹菜任务,我使用这个装饰器(关闭设置中的所有异步作业)

def async_task(func):
    from django.conf import settings
    ALL_TASKS_IS_ASYNC = getattr(settings, 'ALL_TASKS_IS_ASYNC', True)

    @wraps(func)
    def __wrapper__(*args, **kwargs):
        async = kwargs.pop('async', ALL_TASKS_IS_ASYNC)
        if async:
            return func.delay(*args, **kwargs)
        else:
            return func(*args, **kwargs)
    return __wrapper__

And celery_job = async_task(celery_job) in __init__.py file __init__.py文件中的celery_job = async_task(celery_job)

You can use the same idea to append user_login to all tasks 您可以使用相同的想法将user_login附加到所有任务

def async_task(func):
    from django.conf import settings
    ALL_TASKS_IS_ASYNC = getattr(settings, 'ALL_TASKS_IS_ASYNC', True)

    @wraps(func)
    def __wrapper__(*args, **kwargs):
        kwargs['user_login'] = CuserMiddleware.get_user().username
        async = kwargs.pop('async', ALL_TASKS_IS_ASYNC)
        if async:
            return func.delay(*args, **kwargs)
        else:
            return func(*args, **kwargs)
    return __wrapper__

Edit: 编辑:

I think this decorator may optimize refactoring: 我认为这个装饰可能会优化重构:

def task_with_user_info(func):
    @wraps(func)
    def __wrapper__(*args, **kwargs):
        user = CuserMiddleware.get_user()
        kwargs['user_login'] = user.username
        return func(*args, **kwargs)
    if getattr(func, 'delay', None):
        __wrapper__.delay = task_with_user_info(func.delay)
    return __wrapper__


@task_with_user_info
@task
@append_user
def celery_job():
    pass

After this changes you should able to use celery_job as usual. 在此更改后,您应该像往常一样使用celery_job

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM