【问题标题】:database not updated by a task running in celery beat在 celery beat 中运行的任务未更新数据库
【发布时间】:2021-05-17 08:03:08
【问题描述】:

您好,我有一个 celery 任务,假设每 1 小时运行一次以获取密钥,它运行甚至表现得好像它已经更新了数据库,但实际上并没有更新

@app.task
def refresh_token():
    r = requests.get(AUTH_URL, auth=HTTPBasicAuth(CONSUMER_KEY, CONSUMER_SECRET))
    obj = json.loads(r.text)
    obj['expires_in'] = int(obj['expires_in'])
    try:
        mpesa_token = MpesaAccessToken.objects.get(id=1)
        mpesa_token.access_token = obj['access_token']
        mpesa_token.save()
        print(obj)
        print(mpesa_token.access_token)
        print("saved")
    except:
        print(obj)
        mpesa_token = MpesaAccessToken.objects.create(**obj)

    return 1

最后你在日志中打印所有节目,但检查管理面板,值没有更新但是当我使用视图并发出请求然后调用函数时,数据库得到更新,有人知道发生了什么吗

【问题讨论】:

  • 检查您的交易是否以某种方式将自动提交设置为 False
  • 我唯一拥有的装饰器是用于@app.task 的装饰器,否则该怎么做
  • 检查您的 celery 装饰器是否正在提交原子请求,并且您的 celery 任务是否在执行后终止

标签: django django-celery celerybeat


【解决方案1】:

您需要将transaction.atomic() 添加到您的代码中。像这样:

from django.db import transaction

@app.task
def refresh_token():
    with transaction.atomic():
        r = requests.get(AUTH_URL, auth=HTTPBasicAuth(CONSUMER_KEY, CONSUMER_SECRET))
        obj = json.loads(r.text)
        obj['expires_in'] = int(obj['expires_in'])
        try:
            mpesa_token = MpesaAccessToken.objects.get(id=1)
            mpesa_token.access_token = obj['access_token']
            mpesa_token.save()
            print(obj)
            print(mpesa_token.access_token)
            print("saved")
        except:
            print(obj)
            mpesa_token = MpesaAccessToken.objects.create(**obj)
    
        return 1

【讨论】:

    最近更新 更多