web-dev-qa-db-fra.com

Django: Comment gérer les paramètres de développement et de production?

J'ai développé une application de base. Maintenant, au stade du déploiement, il est devenu évident que j’ai besoin de paramètres locaux et de paramètres de production.

Il serait bon de savoir ce qui suit:

  • Comment gérer au mieux les paramètres de développement et de production. 
  • Comment conserver des applications telles que Django-debug-toolbar uniquement dans un environnement de développement.
  • Autres conseils et meilleures pratiques pour les paramètres de développement et de déploiement.
83
Kristian Roebuck

La Django_SETTINGS_MODULE variable d'environnement } __ contrôle le fichier de paramètres que Django chargera. 

Vous créez donc des fichiers de configuration distincts pour vos environnements respectifs (notez qu'ils peuvent bien sûr à la fois import * à partir d'un fichier "paramètres partagés" séparé) et utilisez Django_SETTINGS_MODULE pour contrôler lequel utiliser.

Voici comment:

Comme indiqué dans la documentation Django:

La valeur de Django_SETTINGS_MODULE doit être dans la syntaxe du chemin Python, par exemple. mysite.settings. Notez que le module de paramètres doit être sur le chemin de recherche d'importation Python.

Supposons donc que vous avez créé myapp/production_settings.py et myapp/test_settings.py dans votre référentiel source.

Dans ce cas, vous définissez respectivement Django_SETTINGS_MODULE=myapp.production_settings pour utiliser l'ancien et Django_SETTINGS_MODULE=myapp.test_settings pour utiliser le dernier.


A partir de là, le problème se résume à définir la variable d'environnement Django_SETTINGS_MODULE

Paramétrer Django_SETTINGS_MODULE à l'aide d'un script ou d'un shell

Vous pouvez ensuite utiliser un script d'amorçage ou un gestionnaire de processus pour charger les paramètres corrects (en définissant l'environnement), ou simplement l'exécuter à partir de votre shell avant de démarrer Django: export Django_SETTINGS_MODULE=myapp.production_settings.

Notez que vous pouvez exécuter cet export à tout moment à partir d'un shell - il n'a pas besoin de résider dans votre .bashrc ni quoi que ce soit.

Définition de Django_SETTINGS_MODULE à l'aide d'un gestionnaire de processus

Si vous n'aimez pas écrire un script de démarrage qui définit l'environnement (et qu'il y a de très bonnes raisons de vous sentir ainsi!), Je vous recommande d'utiliser un gestionnaire de processus:


Enfin, notez que vous pouvez tirer parti de la variable PYTHONPATH pour stocker les paramètres dans un emplacement complètement différent (par exemple sur un serveur de production, en les stockant dans /etc/). Cela permet de séparer la configuration des fichiers d'application. Vous pouvez ou non vouloir cela, cela dépend de la structure de votre application. 

82
Thomas Orozco

J'ai généralement un fichier de paramètres par environnement et un fichier de paramètres partagé:

/myproject/
  settings.production.py
  settings.development.py
  shared_settings.py

Chacun de mes fichiers d’environnement a:

try:
    from shared_settings import *
except ImportError:
    pass

Cela me permet de remplacer les paramètres partagés si nécessaire (en ajoutant les modifications sous cette strophe).

Je sélectionne ensuite les fichiers de paramètres à utiliser en le liant à settings.py:

ln -s settings.development.py settings.py
30
Daniel Watkins

Par défaut, utilisez les paramètres de production, mais créez un fichier appelé settings_dev.py dans le même dossier que votre fichier settings.py. Ajouter remplace ici, tel que DEBUG=True.

Ajoutez ceci à votre fichier ~/.bashrc sur l'ordinateur qui sera utilisé pour le développement:

export Django_DEVELOPMENT=true

Au bas de votre fichier settings.py, ajoutez ce qui suit.

# Override production variables if Django_DEVELOPMENT env variable is set
if os.environ.get('Django_DEVELOPMENT') is not None:
    from settings_dev import * 

(Notez que l'importation * devrait généralement être évitée en Python, mais il s'agit d'une circonstance unique.)

Par défaut, les serveurs de production ne remplaceront rien. Terminé!

Comparée aux autres réponses, celle-ci est plus simple car elle ne nécessite pas de mettre à jour PYTHONPATH, ni de régler Django_SETTINGS_MODULE qui ne vous permet de travailler que sur un projet Django à la fois.

30
cs01

Créez plusieurs fichiers settings*.py, en extrapolant les variables devant être modifiées par environnement. Puis à la fin de votre fichier settings.py maître:

try:
  from settings_dev import *
except ImportError:
  pass

Vous conservez les fichiers settings_* séparés pour chaque étape.

En haut de votre fichier settings_dev.py, ajoutez ceci:

import sys
globals().update(vars(sys.modules['settings']))

Pour importer des variables que vous devez modifier.

Cette entrée wiki a plus d’idées sur la manière de diviser vos paramètres.

9
Burhan Khalid

J'utilise awesome Django-configurations , et tous les paramètres sont stockés dans mon settings.py:

from configurations import Configuration

class Base(Configuration):
    # all the base settings here...
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    ...

class Develop(Base):
    # development settings here...
    DEBUG = True 
    ...

class Production(Base):
    # production settings here...
    DEBUG = False

Pour configurer le projet Django, je viens de suivre les docs .

4

Voici l'approche que nous utilisons:

  • un module settings pour fractionner les paramètres en plusieurs fichiers pour en améliorer la lisibilité;
  • un fichier .env.json pour stocker les informations d'identification et les paramètres que nous voulons exclure de notre référentiel git ou qui sont spécifiques à l'environnement;
  • un fichier env.py pour lire le fichier .env.json

Considérant la structure suivante:

...
.env.json           # the file containing all specific credentials and parameters
.gitignore          # the .gitignore file to exclude `.env.json`
project_name/       # project dir (the one which Django-admin.py creates)
  accounts/         # project's apps
    __init__.py
    ...
  ...
  env.py            # the file to load credentials
  settings/
    __init__.py     # main settings file
    database.py     # database conf
    storage.py      # storage conf
    ...
venv                # virtualenv
...

Avec .env.json comme:

{
    "debug": false,
    "allowed_hosts": ["mydomain.com"],
    "Django_secret_key": "my_very_long_secret_key",
    "db_password": "my_db_password",
    "db_name": "my_db_name",
    "db_user": "my_db_user",
    "db_Host": "my_db_Host",
}

Et project_name/env.py:

<!-- language: lang-python -->
import json
import os


def get_credentials():
    env_file_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    with open(os.path.join(env_file_dir, '.env.json'), 'r') as f:
        creds = json.loads(f.read())
    return creds


credentials = get_credentials()

Nous pouvons avoir les paramètres suivants:

<!-- language: lang-py -->
# project_name/settings/__init__.py
from project_name.env import credentials
from project_name.settings.database import *
from project_name.settings.storage import *
...

SECRET_KEY = credentials.get('Django_secret_key')

DEBUG = credentials.get('debug')

ALLOWED_HOSTS = credentials.get('allowed_hosts', [])

INSTALLED_APPS = [
    'Django.contrib.admin',
    'Django.contrib.auth',
    'Django.contrib.contenttypes',
    'Django.contrib.sessions',
    'Django.contrib.messages',
    'Django.contrib.staticfiles',

    ...
]

if DEBUG:
    INSTALLED_APPS += ['debug_toolbar']

...

# project_name/settings/database.py
from project_name.env import credentials

DATABASES = {
    'default': {
        'ENGINE': 'Django.db.backends.postgresql_psycopg2',
        'NAME': credentials.get('db_name', ''),
        'USER': credentials.get('db_user', ''),
        'Host': credentials.get('db_Host', ''),
        'PASSWORD': credentials.get('db_password', ''),
        'PORT': '5432',
    }
}

les avantages de cette solution sont:

  • informations d'identification et configurations spécifiques à l'utilisateur pour le développement local sans modifier le référentiel git;
  • configuration spécifique à l'environnement , vous pouvez avoir, par exemple, trois environnements différents avec trois .env.json différents, tels que dev, staging et production;
  • les informations d'identification ne sont pas dans le référentiel

J'espère que cela aide, faites le moi savoir si vous voyez des mises en garde avec cette solution.

4
Charlesthk

Voici comment je le fais en 6 étapes faciles:

  1. Créez un dossier dans votre répertoire de projet et nommez-le settings

    structure du projet:

    myproject/
           myapp1/
           myapp2/              
           myproject/
                  settings/
    
  2. Créez quatre fichiers python dans le répertoire settings, à savoir init.py, base.py, dev.py et prod.py

    fichiers de paramètres:

    setting/
         init.py
         base.py
         prod.py
         dev.py 
    
  3. Ouvrez init.py et remplissez-le avec le contenu suivant:

    init.py:

    from .base import *
    # you need to set "myproject = 'prod'" as an environment variable 
    # in your OS (on which your website is hosted)
    if os.environ['myproject'] == 'prod':                          
       from .prod import * 
    else:
       from .dev import *   
    
  4. Ouvrez base.py et remplissez-le avec tous les paramètres courants (qui seront utilisés à la fois en production et en développement.), Par exemple:

    base.py:

    import os
    ...
    INSTALLED_APPS = [...]
    MIDDLEWARE = [...]
    TEMPLATES = [{...}]
    ...
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
    MEDIA_ROOT = os.path.join(BASE_DIR, '/path/')
    MEDIA_URL = '/path/'
    
  5. Ouvrez dev.py et incluez ce qui est spécifique au développement, par exemple:

    dev.py:

    DEBUG = True
    ALLOWED_HOSTS = ['localhost']
    ...
    
  6. Ouvrez prod.py et incluez ce qui est spécifique à la production, par exemple:

    prod.py:

    DEBUG = False
    ALLOWED_HOSTS = ['www.example.com']
    LOGGING = [...]
    ...
    
4
Ahtisham

construire sur la réponse de cs01:

si vous rencontrez des problèmes avec la variable d'environnement, définissez sa valeur sur une chaîne (par exemple, je l'ai Django_DEVELOPMENT="true").

J'ai également modifié le workflow de fichiers de cs01 comme suit:

#settings.py
import os
if os.environ.get('Django_DEVELOPMENT') is not None:
    from settings_dev import * 
else:
    from settings_production import *
#settings_dev.py
development settings go here
#settings_production.py
production settings go here

De cette façon, Django n'a pas besoin de lire l'intégralité d'un fichier de paramètres avant d'exécuter le fichier de paramètres approprié. Cette solution est pratique si votre fichier de production nécessite des éléments uniquement sur votre serveur de production.

Remarque: en Python 3, les fichiers importés doivent porter un . (par exemple from .settings_dev import *).

2
Brian Lee

J'utilise la structure de fichier suivante:

project/
   ...
   settings/
   settings/common.py
   settings/local.py
   settings/prod.py
   settings/__init__.py -> local.py

Donc __init__.py est un lien (ln sous unix ou mklink sous windows) avec local.py ou peut être avec prod.py de sorte que la configuration est toujours dans le module project.settings est propre et organisé, et si vous voulez utiliser une configuration particulière, vous pouvez utiliser la variable d'environnement Django_SETTINGS_MODULE à project.settings.prod si vous devez exécuter une commande pour l'environnement de production.

Dans les fichiers prod.py et local.py:

from .shared import *

DATABASE = {
    ...
}

et le fichier shared.py reste global sans configuration spécifique.

1
Felipe Buccioni

Si vous souhaitez conserver 1 fichier de paramètres et que votre système d'exploitation de développement est différent de votre système d'exploitation de production, vous pouvez le placer au bas de votre fichier settings.py:

from sys import platform
if platform == "linux" or platform == "linux2":
    # linux
    # some special setting here for when I'm on my prod server
Elif platform == "darwin":
    # OS X
    # some special setting here for when I'm developing on my mac
Elif platform == "win32":
    # Windows...
    # some special setting here for when I'm developing on my pc

En savoir plus: Comment puis-je vérifier le système d'exploitation en Python?

0
User

Cela semble avoir été répondu, cependant une méthode que j'utilise en combinaison avec le contrôle de version est la suivante:

Configurez un fichier env.py dans le même répertoire que les paramètres de mon environnement de développement local que j’ajoute également à .gitignore:

env.py:

#!usr/bin/python

Django_ENV = True
ALLOWED_HOSTS = ['127.0.0.1', 'dev.mywebsite.com']

.gitignore:

mywebsite/env.py

settings.py:

if os.path.exists(os.getcwd() + '/env.py'):
    #env.py is excluded using the .gitignore file - when moving to production we can automatically set debug mode to off:
    from env import *
else:
    Django_ENV = False

DEBUG = Django_ENV

Je trouve que cela fonctionne et est beaucoup plus élégant - avec env.py, il est facile de voir nos variables d’environnement locales et nous pouvons gérer tout cela sans plusieurs fichiers settings.py ou autres. Cette méthode permet d’utiliser toutes sortes de variables d’environnement locales que nous ne voudrions pas définir sur notre serveur de production. En utilisant le .gitignore via le contrôle de version, nous gardons également tout intégré en toute transparence.

0
user7179686