Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Load production settings for celery

Tags:

django

celery

My Django project has multiple settings file for development, production and testing. And I am using supervisor to manage the celery worker. My question how to load the settings file for celery based on the environment I am in.

like image 508
Cody Avatar asked May 14 '18 18:05

Cody


1 Answers

By using environment variables. Let's say you have the following setting files at the root of your repository.

  • config.settings.development.py
  • config.settings.production.py
  • ...

The recommended way to have your celery instance defined is in your config like celery.py module:

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

# set the default Django settings module for the 'celery' program.
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.production')

app = Celery('proj')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()


@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

Instead of setting the DJANGO_SETTINGS_MODULE variable within the module (I have commented that out) make sure that those are present in the environment at the time that supervisord is started.

To set those variables in your staging, testing, and production system you can execute the following bash command.

E.g. on your production system:

$ export DJANGO_SETTINGS_MODULE=config.settings.production
$ echo $DJANGO_SETTINGS_MODULE

I would also suggest you load them from an .env file. In my opinion thats more convenient. You could do that with for example python-dotenv.


Update

The .env file is mostly unique on your different systems and is usually not under source/version control. By unique I mean for development you may have a more verbose LOG_LEVEL or a different SECRET_KEY, because you don't want them to show up in your source control or want to be able to adjust them without modifying your source files.

So, in your base.py (production.py and development.py are inheriting) you can load the variables from the file with for example:

import os
from dotenv import load_dotenv
load_dotenv()  # .env file has to be in the same directory

# ...
import os
DJANGO_SETTINGS_MODULE = os.getenv("DJANGO_SETTINGS_MODULE")
print(DJANGO_SETTINGS_MODULE)
# ...

I personally don't use the package since I use docker, which has a declarative way of defining an .env file but the code above should give you an idea how it could work. There are similar packages out there like django-environ which is featured in the book Two Scoops of Django. So I would tend to use this instead of python-dotenv, a matter of taste.

like image 152
Yannic Hamann Avatar answered Nov 15 '22 03:11

Yannic Hamann