349 votes

Comment gérer les paramètres locaux et les paramètres de production dans Django ?

Quelle est la méthode recommandée pour gérer les paramètres pour le développement local et le serveur de production ? Certains d'entre eux (comme les constantes, etc.) peuvent être modifiés/accédés dans les deux, mais d'autres (comme les chemins vers les fichiers statiques) doivent rester différents, et ne doivent donc pas être écrasés à chaque fois que le nouveau code est déployé.

Actuellement, j'ajoute toutes les constantes à settings.py . Mais à chaque fois que je modifie une constante localement, je dois la copier sur le serveur de production et éditer le fichier pour les changements spécifiques à la production... :(

Edit : il semble qu'il n'y ait pas de réponse standard à cette question, j'ai accepté la méthode la plus populaire.

3 votes

0 votes

Veuillez consulter django-configurations .

2 votes

La méthode acceptée n'est plus la plus populaire.

329voto

omouse Points 2840

Deux boules de Django : Meilleures pratiques pour Django 1.5 suggère d'utiliser un contrôle de version pour vos fichiers de paramètres et de stocker les fichiers dans un répertoire séparé :

project/
    app1/
    app2/
    project/
        __init__.py
        settings/
            __init__.py
            base.py
            local.py
            production.py
    manage.py

En base.py contient les paramètres courants (tels que MEDIA_ROOT ou ADMIN), tandis que le fichier local.py y production.py ont des paramètres spécifiques au site :

Dans le fichier de base settings/base.py :

INSTALLED_APPS = (
    # common apps...
)

Dans le fichier des paramètres de développement local settings/local.py :

from project.settings.base import *

DEBUG = True
INSTALLED_APPS += (
    'debug_toolbar', # and other apps for local development
)

Dans le fichier des paramètres de production settings/production.py :

from project.settings.base import *

DEBUG = False
INSTALLED_APPS += (
    # other apps for production site
)

Ensuite, lorsque vous exécutez django, vous ajoutez le fichier --settings option :

# Running django for local development
$ ./manage.py runserver 0:8000 --settings=project.settings.local

# Running django shell on the production site
$ ./manage.py shell --settings=project.settings.production

Les auteurs du livre ont également mis en place un modèle de présentation de projet sur Github.

70 votes

Notez qu'au lieu d'utiliser --settings à chaque fois, vous pourriez définir le DJANGO_SETTINGS_MODULE envvar. Cela fonctionne bien avec, par exemple, Heroku : définissez-le globalement pour la production, puis remplacez-le par dev dans votre fichier .env.

9 votes

Utilisation DJANGO_SETTINGS_MODULE env var est la meilleure idée, merci Simon.

0 votes

@kibibu tu veux éditer ma réponse ou je dois ajouter le truc env-var ?

136voto

ohnoes Points 2114

En settings.py :

try:
    from local_settings import *
except ImportError as e:
    pass

Vous pouvez remplacer ce qui est nécessaire dans local_settings.py il devrait rester en dehors de votre contrôle de version. Mais puisque vous parlez de copie, je suppose que vous n'en utilisez aucune ;)

3 votes

Pour faciliter le suivi/déploiement des nouveaux paramètres, utilisez un fichier "local_settings.py" sur les machines de production/test et aucun sur les machines de développement.

8 votes

C'est ce que je fais - en ajoutant ces lignes à la fin de settings.py pour qu'ils puissent remplacer les paramètres par défaut.

1 votes

C'est la méthode la plus propre, surtout si vous utilisez le contrôle de version.

76voto

MiniQuark Points 8927

Au lieu de settings.py utiliser ce modèle :

.
└── settings/
    ├── __init__.py  <= not versioned
    ├── common.py
    ├── dev.py
    └── prod.py

common.py est l'endroit où se trouve la majeure partie de votre configuration.

prod.py importe tout de common et surcharge tout ce qu'il doit surcharger :

from __future__ import absolute_import # optional, but I like it
from .common import *

# Production overrides
DEBUG = False
#...

De même, dev.py importe tout de common.py et surcharge tout ce qu'il doit surcharger.

Enfin, __init__.py est l'endroit où vous décidez des paramètres à charger, et c'est également l'endroit où vous stockez les secrets (ce fichier ne doit donc pas être versionné) :

from __future__ import absolute_import
from .prod import *  # or .dev if you want dev

##### DJANGO SECRETS
SECRET_KEY = '(3gd6shenud@&57...'
DATABASES['default']['PASSWORD'] = 'f9kGH...'

##### OTHER SECRETS
AWS_SECRET_ACCESS_KEY = "h50fH..."

Cette solution me plaît :

  1. Tout est dans votre système de version, sauf les secrets
  2. La plupart des configurations sont regroupées en un seul endroit : common.py .
  3. Les éléments spécifiques à la production y sont insérés prod.py les éléments spécifiques au développement sont placés dans dev.py . C'est simple.
  4. Vous pouvez remplacer des éléments de common.py en prod.py o dev.py et vous pouvez ignorer tout ce qui se trouve dans __init__.py .
  5. C'est du python pur et dur. Pas de hacks de réimportation.

2 votes

J'essaie toujours de comprendre ce qu'il faut mettre dans mes fichiers project.wsgi et manage.py pour le fichier de configuration. Pouvez-vous m'éclairer sur ce point ? Plus précisément, dans mon fichier manage.py, j'ai os.environ.setdefault("DJANGO_SETTINGS_MODULE", "foobar.settings") foobar est un dossier avec un __init__.py et settings est un dossier avec un nom de fichier __init__.py qui contient mes secrets et importe dev.py, qui importe ensuite common.py. EDIT Je n'ai pas installé le module requis. C'est ma faute ! Cela fonctionne très bien !

5 votes

Deux choses : 1) il vaut mieux mettre Debug=True dans votre dev.py plutôt que =False dans votre prod.py. 2) Plutôt que de basculer dans init .py, en utilisant la variable d'environnement DJANGO_SETTINGS_MODULE, ce qui facilitera les déploiements PAAS (par exemple Heroku).

0 votes

Lorsque j'utilise cette configuration dans django 1.8.4 et que j'essaie d'exécuter le serveur, j'obtiens "django.core.exceptions.ImproperlyConfigured : Le paramètre SECRET_KEY ne doit pas être vide", même si j'ai SECRET_KEY sur mon fichier init .py. Ai-je oublié quelque chose ?

20voto

T. Stone Points 10782

J'utilise une version légèrement modifiée des paramètres de type "if DEBUG" publiés par Harper Shelby. Évidemment, en fonction de l'environnement (win/linux/etc.), le code peut avoir besoin d'être légèrement modifié.

Dans le passé, j'utilisais le "if DEBUG", mais j'ai constaté que j'avais parfois besoin de faire des tests avec DEUBG fixé à False. Ce que je voulais vraiment, c'était distinguer si l'environnement était de production ou de développement, ce qui me donnait la liberté de choisir le niveau DEBUG.

PRODUCTION_SERVERS = ['WEBSERVER1','WEBSERVER2',]
if os.environ['COMPUTERNAME'] in PRODUCTION_SERVERS:
    PRODUCTION = True
else:
    PRODUCTION = False

DEBUG = not PRODUCTION
TEMPLATE_DEBUG = DEBUG

# ...

if PRODUCTION:
    DATABASE_HOST = '192.168.1.1'
else:
    DATABASE_HOST = 'localhost'

Je considère toujours cette méthode de paramétrage comme un travail en cours. Je n'ai pas vu de moyen unique de gérer les paramètres de Django qui couvre toutes les bases et en même temps n'est pas un casse-tête total à installer (je ne suis pas d'accord avec les méthodes de 5x les fichiers de paramètres).

0 votes

C'est le genre de choses que permet le fait que les paramètres de Django soient un véritable fichier de code, et c'est ce à quoi je faisais allusion. Je n'ai rien fait de tel moi-même, mais c'est certainement le genre de solution qui pourrait être une meilleure réponse générale que la mienne.

4 votes

Je viens de rencontrer ce problème pour la première fois et j'ai choisi d'utiliser (avec succès !) votre solution, avec une légère différence : J'ai utilisé uuid.getnode() pour trouver l'uuid de mon système. Je teste donc si uuid.getnode() == 12345678901 (en fait un nombre différent) au lieu du test os.environ que vous avez utilisé. Je n'ai pas trouvé de documentation pour me convaincre que os.environ['COMPUTERNAME'] est unique par ordinateur.

0 votes

Os.environ['COMPUTERNAME'] ne fonctionne pas sur Amazon AWS Ubuntu. J'obtiens une KeyError.

14voto

Kai Points 4954

J'utilise un settings_local.py et un settings_production.py. Après avoir essayé plusieurs options, je me suis rendu compte qu'il est facile de perdre du temps avec des solutions complexes alors qu'il est facile et rapide d'avoir simplement deux fichiers de configuration.

Lorsque vous utilisez mod_python/mod_wsgi pour votre projet Django, vous devez le faire pointer vers votre fichier de configuration. Si vous le faites pointer vers app/settings_local.py sur votre serveur local et app/settings_production.py sur votre serveur de production, alors la vie devient facile. Il suffit d'éditer le fichier de configuration approprié et de redémarrer le serveur (le serveur de développement de Django redémarre automatiquement).

2 votes

Et qu'en est-il du serveur de développement local ? Existe-t-il un moyen de dire au serveur web de django (exécuté à l'aide de python manage.py runserver ), quel fichier de paramètres utiliser ?

3 votes

@akv si vous ajoutez --settings=[nom du module] (sans extension .py) à la fin de la commande runserver vous pouvez spécifier le fichier de configuration à utiliser. Si vous faites cela, faites-vous une faveur et créez un fichier shell script/batch avec les paramètres de développement configurés. Croyez-moi, vos doigts vous remercieront.

0 votes

C'est la solution que j'utilise. Il est fastidieux d'élaborer un fichier de paramètres qui sera utilisé à la fois pour la production et le développement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X