Two Scoops of Django: Best Practices for Django 1.8

Author: Audrey Roy Greenfeld, Daniel Roy Greenfeld
4.5
This Month Stack Overflow 1

Two Scoops of Django: Best Practices for Django 1.8

4.5

Review Date:

Comments

by anonymous   2019-01-13

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.

by anonymous   2017-08-20

You can create separate static folder for all apps and set STATICFILES_DIRS accordingly.

I personally use the following project layout

project/apps/app_1
             ...
             app_n
             static        <- static files for all apps
             templates     <- templates for all apps

       /config/...
               settings.py
               ...

which I borrowed from Two Scoops of Django book