Celery 和 Django,查询导致 ProgrammingError
Celery and Django, queries cause ProgrammingError
我正在使用 cookiecutter-django 构建一个小型 Django 项目,我需要在后台执行 运行 任务。尽管我使用 cookiecutter 设置了项目,但我在使用 Celery 时遇到了一些问题。
假设我有一个名为 Job
的模型 class,其中包含三个字段:默认主键、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
的类似问题。但是我已经这样做了,这不是解决方案,否则 Django 将无法在有或没有 Celery 的情况下执行有问题的代码。
这是怎么回事?我的所有模型对象都得到了完全相同的行为。
编辑:
为了以防万一,我使用的是 Django 2.0.2 和 Celery 4.1
我发现了我的错误。如果您确定您的数据库已正确迁移并且出现如上错误:很可能是您无法连接到数据库。可能会访问您的数据库主机,但不会访问数据库本身。
这意味着您的配置可能已损坏。
为什么配置错误:在 cookiecutter-django 的情况下,Celery 可能会在 Mac 上以 root 身份抱怨 运行,所以我设置了环境变量 C_FORCE_ROOT
在我的 docker-compose 文件中。 [仅适用于本地,您应该永远不要在生产中这样做!]在此处阅读有关此问题的信息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
变量添加到该容器,一切又开始正常工作了。我犯了一个愚蠢的错误,但我希望我能为有这个答案的人节省一些时间。
我正在使用 cookiecutter-django 构建一个小型 Django 项目,我需要在后台执行 运行 任务。尽管我使用 cookiecutter 设置了项目,但我在使用 Celery 时遇到了一些问题。
假设我有一个名为 Job
的模型 class,其中包含三个字段:默认主键、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
的类似问题。但是我已经这样做了,这不是解决方案,否则 Django 将无法在有或没有 Celery 的情况下执行有问题的代码。
这是怎么回事?我的所有模型对象都得到了完全相同的行为。
编辑: 为了以防万一,我使用的是 Django 2.0.2 和 Celery 4.1
我发现了我的错误。如果您确定您的数据库已正确迁移并且出现如上错误:很可能是您无法连接到数据库。可能会访问您的数据库主机,但不会访问数据库本身。
这意味着您的配置可能已损坏。
为什么配置错误:在 cookiecutter-django 的情况下,Celery 可能会在 Mac 上以 root 身份抱怨 运行,所以我设置了环境变量 C_FORCE_ROOT
在我的 docker-compose 文件中。 [仅适用于本地,您应该永远不要在生产中这样做!]在此处阅读有关此问题的信息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
变量添加到该容器,一切又开始正常工作了。我犯了一个愚蠢的错误,但我希望我能为有这个答案的人节省一些时间。