【问题标题】:Celery and Django, queries cause ProgrammingErrorCelery 和 Django,查询导致 ProgrammingError
【发布时间】:2018-03-05 18:32:16
【问题描述】:

我正在使用 cookiecutter-django 构建一个小型 Django 项目,我需要在后台运行任务。尽管我使用 cookiecutter 设置了项目,但我在使用 Celery 时遇到了一些问题。

假设我有一个名为 Job 的模型类,其中包含三个字段:默认主键、UUID 和日期:

class Job(models.Model):
    access_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    date = models.DateTimeField(auto_now_add=True)

现在,如果我在 Django 视图中执行以下操作,一切正常:

job1 = Job()
job1.save()
logger.info("Created job {}".format(job1.access_id))

job2 = Job.objects.get(access_id=job1.access_id)
logger.info("Retrieved job {}".format(job2.access_id))

如果我创建一个完全相同的 Celery 任务,我会收到错误:

django.db.utils.ProgrammingError: relation "metagrabber_job" does not exist
LINE 1: INSERT INTO "metagrabber_job" ("access_id", "date") VALUES ('e8a2...

这就是我的 Postgres docker 容器当时所说的:

postgres_1      | 2018-03-05 18:23:23.008 UTC [85] STATEMENT:  INSERT INTO "metagrabber_job" ("access_id", "date") VALUES ('e8a26945-67c7-4c66-afd1-bbf77cc7ff6d'::uuid, '2018-03-05T18:23:23.008085+00:00'::timestamptz) RETURNING "metagrabber_job"."id"

有趣的是,如果我查看我的 Django 管理员,我确实看到创建了一个 Job 对象,但它带有不同的 UUID,如日志所说..

如果我随后设置 CELERY_ALWAYS_EAGER = False 让 Django 执行任务而不是 Celery:瞧,它会再次运行而不会出错。但在 Django 中运行任务并不是重点。

我做了很多搜索,只发现了类似的问题,解决方案是运行manage.py migrate。但是我已经这样做了,这不是解决方案,否则无论有没有 Celery,Django 都无法执行有问题的代码。

那么发生了什么?我的所有模型对象都得到了完全相同的行为。

编辑: 以防万一,我使用的是 Django 2.0.2 和 Celery 4.1

【问题讨论】:

    标签: django celery cookiecutter-django


    【解决方案1】:

    我发现了我的错误。如果您确定您的数据库已正确迁移并且您收到上述错误:很可能是您无法连接到数据库。可能会到达您的数据库主机,但不会到达数据库本身。

    这意味着您的配置可能已损坏。

    为什么配置错误:在 cookiecutter-django 的情况下,Celery 可能会抱怨在 Mac 上以 root 身份运行,因此我在 docker-compose 文件中设置了环境变量 C_FORCE_ROOT。 [仅限本地,您应该永远不要在生产环境中这样做!] 在此处阅读有关此问题的信息 https://github.com/pydanny/cookiecutter-django/issues/1304

    配置的相关部分如下所示:

    django: &django
      build:
        context: .
        dockerfile: ./compose/local/django/Dockerfile
      depends_on:
        - postgres
      volumes:
        - .:/app
      environment:
        - POSTGRES_USER=asdfg123456
        - USE_DOCKER=yes
      ports:
        - "8000:8000"
        - "3000:3000"
      command: /start.sh
    
    celeryworker:
      <<: *django
      depends_on:
        - redis
        - postgres
      environment:
        - C_FORCE_ROOT=true
      ports: []
      command: /start-celeryworker.sh
    

    然而通过 docker-compose 文件设置此环境变量会阻止在 celeryworker 容器上设置 django 环境变量,从而使我的数据库配置不存在。

    我手动将POSTGRES_USER 变量添加到该容器中,然后事情又开始工作了。这是我的愚蠢错误,但我希望我能为有这个答案的人节省一些时间。

    【讨论】:

      猜你喜欢
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2013-10-13
      • 2021-09-17
      • 1970-01-01
      相关资源
      最近更新 更多