Comment gérer les paramètres locaux vs production dans Django?
Quelle est la manière recommandée de 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 certains d'entre eux (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 change une constante localement, je dois la copier sur le serveur de production et éditer le fichier pour changements spécifiques à la production... :(
Edit: on dirait qu'il n'y a pas de réponse standard à cette question, j'ai accepté la méthode la plus populaire.
20 réponses
Dans 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 hors de votre contrôle de version alors. Mais puisque vous mentionnez la copie, je suppose que vous n'utilisez aucun;)
Deux Scoops de Django: meilleures pratiques pour Django 1.5 suggère d'utiliser le 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
Le fichier base.py
contient des paramètres communs (tels que MEDIA_ROOT ou ADMIN), tandis que local.py
et 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 de 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 paramètres de production du fichier 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 l'option --settings
:
# 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 exemple de modèle de mise en page de projet sur Github.
Au lieu de settings.py
, Utilisez cette mise en page:
.
└── settings/
├── __init__.py <= not versioned
├── common.py
├── dev.py
└── prod.py
common.py
est l'endroit où vit la plupart de votre configuration.
prod.py
importe tout de common, et remplace tout ce dont il a besoin pour remplacer:
from __future__ import absolute_import # optional, but I like it
from .common import *
# Production overrides
DEBUG = False
#...
De même, dev.py
importe tout à partir de common.py
et remplace tout ce qu'il doit remplacer.
Enfin, {[8] } est l'endroit où vous décidez quels paramètres charger, et c'est aussi l'endroit où vous stockez des secrets (donc ce fichier ne devrait 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..."
Ce que j'aime dans cette solution est:
- Tout est dans votre système de gestion des versions, à l'exception des secrets
- la plupart des configurations sont en un seul endroit:
common.py
. - les choses spécifiques au Prod vont dans
prod.py
, les choses spécifiques au dev vont dansdev.py
. C'est simple. - Vous pouvez remplacer des éléments de
common.py
dansprod.py
oudev.py
, et vous pouvez remplacer n'importe quoi dans__init__.py
. - c'est Python simple. Pas de hacks de réimportation.
J'utilise une version légèrement modifiée du style de paramètres" if DEBUG " que Harper Shelby a posté. Évidemment, en fonction de l'environnement (win/linux/etc.) le code pourrait avoir besoin d'être modifié un peu.
J'utilisais dans le passé le "IF DEBUG" mais j'ai trouvé que de temps en temps je devais faire des tests avec DEUBG défini sur False. Ce que je voulais vraiment distinguer si l'environnement était la production ou le développement, ce qui m'a donné la liberté de choisir le niveau de débogage.
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 voudrais toujours considérez cette façon de paramètres un travail en cours. Je n'ai pas vu une façon de gérer les paramètres Django qui couvraient toutes les bases et en même temps n'était pas un problème total à configurer (Je ne suis pas en bas avec les méthodes de fichiers de paramètres 5x).
J'utilise un settings_local.py et un settings_production.py. après avoir essayé plusieurs options, j'ai trouvé qu'il est facile de perdre du temps avec des solutions complexes lorsque le simple fait d'avoir deux fichiers de paramètres est facile et rapide.
Lorsque vous utilisez mod_python/mod_wsgi pour votre projet Django, vous devez pointer vers votre fichier de paramètres. Si vous le pointez vers app/settings_local.py sur votre serveur local et app/settings_production.py sur votre serveur de production, la vie devient facile. Juste modifier le fichier de paramètres et redémarrez le serveur (Django development server redémarrera automatiquement).
Je gérer mes configurations avec l'aide de django-split-paramètres.
C'est un remplacement pour les paramètres par défaut. Il est simple, mais configurable. Et le refactoring de vos paramètres existants n'est pas nécessaire.
Voici un petit exemple (fichier example/settings/__init__.py
):
from split_settings.tools import optional, include
import os
if os.environ['DJANGO_SETTINGS_MODULE'] == 'example.settings':
include(
'components/default.py',
'components/database.py',
# This file may be missing:
optional('local_settings.py'),
scope=globals()
)
C'est ça.
Mettre à jour
J'ai écrit un article de blog sur la gestion des paramètres de django
avec django-split-sttings
. Avoir un coup d'oeil!
Le problème avec la plupart de ces solutions est que vos paramètres locaux sont appliqués avant les paramètres communs, ou après.
Il est donc impossible de remplacer des choses comme
- les paramètres spécifiques à env définissent les adresses du pool memcached, et dans le fichier de paramètres principal, cette valeur est utilisée pour configurer le moteur de cache
- les paramètres spécifiques à env ajouter ou supprimer des applications / middleware à celui par défaut
Au même temps.
Une solution peut être implémentée en utilisant des fichiers de configuration de style"ini" avec la classe ConfigParser. Il prend en charge plusieurs fichiers, l'interpolation de chaîne paresseuse, les valeurs par défaut et beaucoup d'autres goodies. Une fois qu'un certain nombre de fichiers ont été chargés, d'autres fichiers peuvent être chargés et leurs valeurs remplaceront les précédentes, le cas échéant.
Vous chargez un ou plusieurs fichiers de configuration, en fonction de l'adresse de la machine, des variables d'environnement et même des valeurs des fichiers de configuration précédemment chargés. Puis vous utilisez simplement les valeurs analysées pour remplir les paramètres.
Une stratégie que j'ai utilisée avec succès a été:
- Charge un fichier
defaults.ini
par défaut - vérifiez le nom de la machine et chargez tous les fichiers correspondant au nom de domaine complet inversé, de la correspondance la plus courte à la correspondance la plus longue (donc, j'ai chargé
net.ini
, puisnet.domain.ini
, puisnet.domain.webserver01.ini
, chacun remplaçant éventuellement les valeurs précédentes). Ce compte également pour les machines des développeurs, afin que chacun puisse configurer son pilote de base de données préféré, etc. pour le développement local - Vérifiez s'il y a un" nom de cluster " déclaré, et dans ce cas load
cluster.cluster_name.ini
, qui peut définir des choses comme les adresses IP de base de données et de cache
Comme exemple de quelque chose que vous pouvez réaliser avec ceci, vous pouvez définir une valeur de "sous-domaine" par-env, qui est ensuite utilisée dans les paramètres par défaut (comme hostname: %(subdomain).whatever.net
) pour définir tous les noms d'hôte nécessaires et les choses de cookie que django doit fonctionner.
C'est aussi sec que je pourrais obtenir, la plupart des fichiers (existants) avaient juste 3 ou 4 paramètre. En plus de cela, j'ai dû gérer la configuration du client, donc un ensemble supplémentaire de fichiers de configuration (avec des choses comme les noms de base de données, les utilisateurs et les mots de passe, le sous-domaine assigné, etc.) existait, un ou plusieurs par client.
On peut l'adapter aussi bas ou aussi haut que nécessaire, il suffit de mettre dans le fichier de configuration les clés que vous voulez configurer par environnement, et une fois qu'il y a besoin d'une nouvelle configuration, mettez la valeur précédente dans la configuration par défaut, et remplacez-la où nécessaire.
Ce système s'est avéré fiable et fonctionne bien avec le contrôle de version. Il a été utilisé pendant longtemps pour gérer deux clusters d'applications distincts (15 instances distinctes ou plus du site django par machine), avec plus de 50 clients, où les clusters changeaient de taille et de membres en fonction de l'humeur du sysadmin...
Rappelez-vous cela settings.py est un fichier de code en direct. En supposant que vous n'avez pas défini de débogage en production (ce qui est une bonne pratique), vous pouvez faire quelque chose comme:
if DEBUG:
STATIC_PATH = /path/to/dev/files
else:
STATIC_PATH = /path/to/production/files
Assez basique, mais vous pourriez, en théorie, aller jusqu'à n'importe quel niveau de complexité basé uniquement sur la valeur de DEBUG - ou toute autre variable ou vérification de code que vous vouliez utiliser.
Je travaille aussi avec Laravel et j'aime l'implémentation là-bas. J'ai essayé de l'imiter et de le combiner avec la solution proposée par T. Stone (Regardez ci-dessus):
PRODUCTION_SERVERS = ['*.webfaction.com','*.whatever.com',]
def check_env():
for item in PRODUCTION_SERVERS:
match = re.match(r"(^." + item + "$)", socket.gethostname())
if match:
return True
if check_env():
PRODUCTION = True
else:
PRODUCTION = False
DEBUG = not PRODUCTION
Peut-être que quelque chose comme ça vous aiderait.
Ma solution à ce problème est aussi un peu un mélange de certaines solutions déjà dit ici:
- je garde un fichier appelé
local_settings.py
que aUSING_LOCAL = True
dev etUSING_LOCAL = False
en prod - Dans
settings.py
je fais une importation sur ce fichier pour obtenir leUSING_LOCAL
paramètre
Je base ensuite tous mes paramètres dépendants de l'environnement sur celui-ci:
DEBUG = USING_LOCAL
if USING_LOCAL:
# dev database settings
else:
# prod database settings
Je préfère cela à deux séparés settings.py les fichiers que je dois maintenir car je peux garder mes paramètres structurés en un seul Fichier plus facile que de les avoir répartis sur plusieurs fichiers. Comme ça, quand je mets à jour un paramètre, Je n'oublie pas de le faire pour les deux environnements.
Bien sûr que chaque méthode a ses inconvénients et celle-ci ne fait pas exception. Le problème ici est que je ne peux pas écraser le fichier local_settings.py
chaque fois que je pousse mes modifications en production, ce qui signifie que je ne peux pas simplement copier tous les fichiers aveuglément, mais c'est quelque chose que je peux vivre avec.
Pour la plupart de mes projets, j'utilise le modèle suivant:
- Créer settings_base.py où je stocke les paramètres communs à tous les environnements
- chaque fois que j'ai besoin d'utiliser un nouvel environnement avec des exigences spécifiques, je crée un nouveau fichier de paramètres (par exemple. settings_local.py) qui hérite du contenu de settings_base.py et remplace / ajoute des variables de paramètres appropriés (
from settings_base import *
)
(à exécuter manage.py avec le fichier de paramètres personnalisés, vous utilisez simplement l'option de commande --settings: manage.py <command> --settings=settings_you_wish_to_use.py
)
J'utilise une variation de ce que jpartogi mentionné ci-dessus, que je trouve un peu plus courte:
import platform
from django.core.management import execute_manager
computername = platform.node()
try:
settings = __import__(computername + '_settings')
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file '%r_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % (computername, __file__))
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
Fondamentalement sur chaque ordinateur (développement ou production) j'ai le approprié hostname_settings.py fichier qui est chargé dynamiquement.
Il y a aussi des paramètres de classe Django. Je suis personnellement un grand fan de lui. Il est construit par L'une des personnes les plus actives sur L'IRC Django. Vous utiliseriez des variables d'environnement pour définir les choses.
TL; DR: l'astuce consiste à modifier os.environment
avant d'importer settings/base.py
dans n'importe quel settings/<purpose>.py
, cela simplifiera grandement les choses.
Penser à tous ces fichiers entrelacés me donne un mal de tête.
Combiner, importer (parfois conditionnellement), remplacer, Patcher ce qui était déjà défini dans le cas où le paramètre DEBUG
a été modifié plus tard.
Ce qu'est un cauchemar!
Au fil des ans, je suis passé par toutes les solutions différentes. Ilsun peu travaillent, mais sont si douloureux à gérer.
WTF! Avons-nous vraiment besoin de tous ces tracas? Nous avons commencé avec un seul fichier settings.py
.
Maintenant, nous avons besoin d'une documentation juste pour combiner correctement tous ces ensemble dans un ordre correct!
J'espère que j'ai enfin frappé le (mon) sweet spot avec la solution ci-dessous.
Résumons les objectifs (certains communs, certains miens)
Gardez les secrets un secret-ne les stockez pas dans un repo.
Définir / lire les clés et les secrets via les paramètres d'environnement, 12 facteur style .
Avoir des valeurs par défaut de secours raisonnables. Idéalement pour le développement local, vous n'avez besoin de rien de plus à côté des valeurs par défaut.
...mais essayez de garder la production par défaut en toute sécurité. Il est préférable de manquer un paramètre override localement, que d'avoir à se rappeler d'ajuster les paramètres par défaut en toute sécurité pour la production.
Avoir la possibilité de changer de
DEBUG
on/off dans une manière qui peut avoir un effet sur d'autres paramètres (par exemple. en utilisant javascript compressé ou pas).La commutation entre les paramètres de destination, comme local / testing/staging / production, ne devrait être basée que sur
DJANGO_SETTINGS_MODULE
, rien de plus....mais permettez une paramétrisation supplémentaire via des paramètres d'environnement tels que
DATABASE_URL
....permettez-leur également d'utiliser différents paramètres de but et de les exécuter localement côte à côte, par exemple. installation de production sur la machine de développeur local, pour accéder à la base de données de production ou au style compressé de test de fumée feuille.
Échoue si une variable d'environnement n'est pas explicitement définie (nécessitant une valeur vide au minimum), en particulier en production, par exemple.
EMAIL_HOST_PASSWORD
.Répondre à la valeur par défaut
DJANGO_SETTINGS_MODULE
définie manage.py pendant django-admin startprojectGardez les conditions au minimum, si la condition est le type d'environnement prévu (par exemple. pour le fichier journal de jeu de production et sa rotation), remplacez les paramètres dans les paramètres associés fichier.
Ne pas
Ne laissez pas django lire le paramètre DJANGO_SETTINGS_MODULE dans un fichier.
Pouah! Pensez à la façon dont meta c'est. Si vous avez besoin d'un fichier (comme docker env) lisez cela dans l'environnement avant de regarder un processus django.Ne remplacez pas DJANGO_SETTINGS_MODULE dans le code de votre projet/Application, par exemple. basé sur le nom d'hôte ou nom du processus.
Si vous êtes paresseux pour définir la variable d'environnement (comme poursetup.py test
) faire en outillage juste avant d'exécuter votre code de projet.Évitez la magie et la correction de la façon dont django lit ses paramètres, prétraitez les paramètres mais n'interférez pas par la suite.
Pas de logique compliquée basée sur un non-sens. La Configuration doit être fixée et matérialisée non calculée à la volée. Fournir des valeurs par défaut de secours est juste assez logique ici.
Voulez-vous vraiment déboguer, pourquoi localement vous avez un ensemble de paramètres correct mais en production sur un serveur distant, sur une des cent machines, quelque chose calculé différemment? Oh! Les tests unitaires? Pour les réglages? Vraiment?
Solution
Ma stratégie consiste en un excellent django-environ utilisé avec les fichiers de style ini
,
fournir os.environment
par défaut pour le développement local, certains fichiers settings/<purpose>.py
minimes et courts qui ont un
import settings/base.py
APRÈS le os.environment
a été créé à partir d'un INI
fichier. Cela nous donne effectivement une sorte d'injection de paramètres.
L'astuce ici est de modifier os.environment
avant d'importer settings/base.py
.
Voir l'exemple complet d'aller faire le repo: https://github.com/wooyek/django-settings-strategy
.
│ manage.py
├───data
└───website
├───settings
│ │ __init__.py <-- imports local for compatybility
│ │ base.py <-- almost all the settings, reads from proces environment
│ │ local.py <-- a few modifications for local development
│ │ production.py <-- ideally is empy and everything is in base
│ │ testing.py <-- mimics production with a reasonable exeptions
│ │ .env <-- for local use, not kept in repo
│ __init__.py
│ urls.py
│ wsgi.py
Paramètres/.env
A valeurs par défaut pour le développement local. Un fichier secret, pour définir principalement les variables d'environnement requises.
Définissez-les sur des valeurs vides si elles ne sont pas requises dans le développement local.
Nous fournissons des valeurs par défaut ici et non dans settings/base.py
pour échouer sur une autre machine si elles sont manquantes dans le environnement.
Settings/local.py
Ce qui se passe ici, c'est le chargement de l'environnement à partir de settings/.env
, puis l'importation des paramètres communs
de settings/base.py
. Après cela, nous pouvons remplacer quelques-uns pour faciliter le développement local.
import logging
import environ
logging.debug("Settings loading: %s" % __file__)
# This will read missing environment variables from a file
# We wan to do this before loading a base settings as they may depend on environment
environ.Env.read_env(DEBUG='True')
from .base import *
ALLOWED_HOSTS += [
'127.0.0.1',
'localhost',
'.example.com',
'vagrant',
]
# https://docs.djangoproject.com/en/1.6/topics/email/#console-backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
LOGGING['handlers']['mail_admins']['email_backend'] = 'django.core.mail.backends.dummy.EmailBackend'
# Sync task testing
# http://docs.celeryproject.org/en/2.5/configuration.html?highlight=celery_always_eager#celery-always-eager
CELERY_ALWAYS_EAGER = True
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
Settings/production.py
Pour la production, nous ne devrions pas nous attendre à un fichier d'environnement, mais il est plus facile d'en avoir un si nous testons quelque chose.
Mais de toute façon, de peur de fournir quelques valeurs par défaut en ligne, donc settings/base.py
peut répondre en conséquence.
environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *
, Le point d'intérêt principal ici sont DEBUG
et ASSETS_DEBUG
remplace,
ils ne seront appliqués au python {[31] } que S'ils sont absents de l'environnement et du fichier.
Ce seront nos défauts de production, pas besoin de les mettre dans l'environnement ou le fichier, mais ils peuvent être remplacés si nécessaire. Neat!
Settings/base.py
Ce sont vos paramètres django principalement vanille, avec quelques conditions et beaucoup de les lire de l'environnement. Presque tout est ici, en gardant tous les environnements prévus cohérents et aussi similaires que possible.
Les principales différences sont ci-dessous (j'espère que ces sont explicites):
import environ
# https://github.com/joke2k/django-environ
env = environ.Env()
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Where BASE_DIR is a django source root, ROOT_DIR is a whole project root
# It may differ BASE_DIR for eg. when your django project code is in `src` folder
# This may help to separate python modules and *django apps* from other stuff
# like documentation, fixtures, docker settings
ROOT_DIR = BASE_DIR
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG', default=False)
INTERNAL_IPS = [
'127.0.0.1',
]
ALLOWED_HOSTS = []
if 'ALLOWED_HOSTS' in os.environ:
hosts = os.environ['ALLOWED_HOSTS'].split(" ")
BASE_URL = "https://" + hosts[0]
for host in hosts:
host = host.strip()
if host:
ALLOWED_HOSTS.append(host)
SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=False)
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
if "DATABASE_URL" in os.environ: # pragma: no cover
# Enable database config through environment
DATABASES = {
# Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
'default': env.db(),
}
# Make sure we use have all settings we need
# DATABASES['default']['ENGINE'] = 'django.contrib.gis.db.backends.postgis'
DATABASES['default']['TEST'] = {'NAME': os.environ.get("DATABASE_TEST_NAME", None)}
DATABASES['default']['OPTIONS'] = {
'options': '-c search_path=gis,public,pg_catalog',
'sslmode': 'require',
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
# 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
'NAME': os.path.join(ROOT_DIR, 'data', 'db.dev.sqlite3'),
'TEST': {
'NAME': os.path.join(ROOT_DIR, 'data', 'db.test.sqlite3'),
}
}
}
STATIC_ROOT = os.path.join(ROOT_DIR, 'static')
# django-assets
# http://django-assets.readthedocs.org/en/latest/settings.html
ASSETS_LOAD_PATH = STATIC_ROOT
ASSETS_ROOT = os.path.join(ROOT_DIR, 'assets', "compressed")
ASSETS_DEBUG = env('ASSETS_DEBUG', default=DEBUG) # Disable when testing compressed file in DEBUG mode
if ASSETS_DEBUG:
ASSETS_URL = STATIC_URL
ASSETS_MANIFEST = "json:{}".format(os.path.join(ASSETS_ROOT, "manifest.json"))
else:
ASSETS_URL = STATIC_URL + "assets/compressed/"
ASSETS_MANIFEST = "json:{}".format(os.path.join(STATIC_ROOT, 'assets', "compressed", "manifest.json"))
ASSETS_AUTO_BUILD = ASSETS_DEBUG
ASSETS_MODULES = ('website.assets',)
Le Dernier bit montre la puissance ici. ASSETS_DEBUG
a une valeur par défaut raisonnable,
qui peut être remplacé dans settings/production.py
et même que cela peut être remplacé par un paramètre d'environnement! Yay!!!
En effet, nous avons une hiérarchie mixte de importance:
- settings/.py -définit les valeurs par défaut en fonction du but, ne stocke pas de secrets
- settings/base.py - est principalement contrôlée par l'environnement
- processus environnement paramètres - 12 facteur bébé!
- paramètres/.env-paramètres par défaut locaux pour un démarrage facile
Je le différencie en manage.py et créé deux fichiers de paramètres distincts: local_settings.py et prod_settings.py.
Dans manage.py je vérifie si le serveur est un serveur local ou un serveur de production. S'il s'agit d'un serveur local il se chargerait local_settings.py et c'est un serveur de production qu'il chargerait prod_settings.py. fondamentalement, c'est à quoi cela ressemblerait:
#!/usr/bin/env python
import sys
import socket
from django.core.management import execute_manager
ipaddress = socket.gethostbyname( socket.gethostname() )
if ipaddress == '127.0.0.1':
try:
import local_settings # Assumed to be in the same directory.
settings = local_settings
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'local_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file local_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
else:
try:
import prod_settings # Assumed to be in the same directory.
settings = prod_settings
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'prod_settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file prod_settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
J'ai trouvé plus facile de séparer le fichier de paramètres en deux fichiers distincts au lieu de faire beaucoup d'ifs à l'intérieur du fichier de paramètres.
Comme alternative pour maintenir un fichier différent si vous wiil: Si vous utilisez git ou tout autre VCS pour pousser les codes du local au serveur, ce que vous pouvez faire est d'ajouter le fichier de paramètres .gitignore.
Cela vous permettra d'avoir un contenu différent dans les deux endroits, sans aucun problème. Ainsi, sur le serveur, vous pouvez configurer une version indépendante de settings.py et toutes les modifications apportées sur le local ne refléteront pas sur le serveur et vice versa.
En outre, il supprimera le settings.py fichier de GitHub aussi, la grande faute, que j'ai vu beaucoup de débutants faire.
Pour utiliser une configuration différente de settings
sur un environnement différent, créez un fichier de paramètres différent. Et dans votre script de déploiement, démarrez le serveur en utilisant --settings=<my-settings.py>
paramètre, via lequel vous pouvez utiliser différents paramètres sur différents environnements.
Avantages de l'utilisation de cette approche:
Vos paramètres seront modulaire en fonction de chaque environnement
Vous pouvez importer les
master_settings.py
contenant la configuration de base dans leenvironmnet_configuration.py
et remplacer les valeurs que vous souhaitez modifier dans cet environnement.Si vous avez une équipe énorme, chaque développeur peut avoir son propre
local_settings.py
qu'il peut ajouter au référentiel de code sans aucun risque de modifier la configuration du serveur. Vous pouvez ajouter ces paramètres locaux de.gitnore
si vous utilisez git ou.hginore
{si vous[10]}Mercurial pour Contrôle de Version (ou tout autre). De cette façon les paramètres locaux ne seront même pas la partie de la base de code réelle en la gardant propre.
1-Créez un nouveau dossier dans votre application et nommez-le.
2-Créez maintenant un nouveau fichier init.PY et à l'intérieur écrivez
from .base import *
try:
De .importation locale *
except:
Passer
try:
De .production importation *
except:
Passer
3-Créer trois nouveaux fichiers dans le nom du dossier Paramètres local.py et production.py et base.py
4 - Intérieur base.py copiez tout le contenu des paramètres précédents.P Dossier et le renommer avec quelque chose différent disons old_settings.py
5-In base.py changez votre chemin BASE_DIR pour pointer vers votre nouveau chemin de réglage
Ancien chemin - > BASE_DIR = os.chemin.dirname (os.chemin.dirname (os.chemin.abspath(fichier)))
Nouveau chemin - > BASE_DIR = os.chemin.dirname (os.chemin.dirname (os.chemin.dirname (os.chemin.abspath(fichier)))
Maintenant, le projet dir peut être structuré et gérable entre la production et le développement local.
Mes paramètres ont été divisés comme suit
settings/
|
|- base.py
|- dev.py
|- prod.py
, Nous avons 3 environnements
- dev
- mise en scène
- production
Maintenant, évidemment, la mise en scène et la production devraient avoir le maximum d'environnement similaire possible. Nous avons donc gardé prod.py
pour les deux.
Mais il y avait un cas où je devais identifier le serveur en cours d'exécution est un serveur de production. La réponse de @T. Stone m'a aidé à écrire check comme suit.
from socket import gethostname, gethostbyname
PROD_HOSTS = ["webserver1", "webserver2"]
DEBUG = False
ALLOWED_HOSTS = [gethostname(), gethostbyname(gethostname()),]
if any(host in PROD_HOSTS for host in ALLOWED_HOSTS):
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
J'ai trouvé les réponses ici très utiles. (Cela a été plus définitivement résolu? La dernière réponse il y a un an.) Après avoir examiné toutes les approches énumérées, j'ai trouvé une solution que je n'ai pas vue énumérée ici.
Mes critères étaient:
- Tout devrait être dans le contrôle de la source. Je n'aime pas fiddly bits qui traînent.
- idéalement, conservez les paramètres dans un fichier. J'oublie des choses si Je ne les regarde pas:)
- Aucune modification manuelle pour déployer. Devrait être capable de tester / push / deploy avec une seule commande fabric.
- évitez les fuites de paramètres de développement dans la production.
- gardez le plus près possible de la disposition Django "standard" (*tousse*).
Je pensais que l'allumage de la machine hôte avait du sens, mais j'ai ensuite pensé que le vrai problème ici était différents paramètres pour différents environnements , et j'ai eu un moment aha. Je mets ce code à la fin de mon settings.py fichier:
try:
os.environ['DJANGO_DEVELOPMENT_SERVER'] # throws error if unset
DEBUG = True
TEMPLATE_DEBUG = True
# This is naive but possible. Could also redeclare full app set to control ordering.
# Note that it requires a list rather than the generated tuple.
INSTALLED_APPS.extend([
'debug_toolbar',
'django_nose',
])
# Production database settings, alternate static/media paths, etc...
except KeyError:
print 'DJANGO_DEVELOPMENT_SERVER environment var not set; using production settings'
De cette façon, l'application par défaut aux paramètres de production, ce qui signifie que vous êtes explicitement "whitelisting" votre environnement de développement. Il est beaucoup plus sûr d'oublier de définir la variable d'environnement localement que si c'était l'inverse et que vous avez oublié de définir quelque chose en production et de laisser certains paramètres de Développement être utilisés.
Lors du développement local, soit à partir du shell ou dans un .bash_profile ou où:
$ export DJANGO_DEVELOPMENT_SERVER=yep
(ou si vous développez sur Windows, définissez via le Panneau de contrôle ou quel que soit son nom ces jours-ci... Windows l'a toujours rendu si obscur que vous pouvez définir des variables d'environnement.)
Avec cette approche, les paramètres dev sont tous en un seul endroit (standard), et remplacent simplement ceux de production si nécessaire. Tout bourrage avec les paramètres de développement devrait être complètement sûr de s'engager dans le contrôle de la source sans impact sur la production.