web-dev-qa-db-fra.com

Paramètres locaux de Django

J'essaie d'utiliser local_setting dans Django 1.2, mais cela ne fonctionne pas pour moi. Pour le moment, j'ajoute simplement local_settings.py à mon projet.

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'Django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'Oracle'.
        'NAME': 'banco1',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'Host': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

local_settings.py

DATABASES = {
    'default': {
        'ENGINE': 'Django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'Oracle'.
        'NAME': 'banco2',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'Host': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

Le problème est que local_settings.py ne remplace pas settings.py .

64
Michel Andrade

Vous ne pouvez pas simplement ajouter local_settings.py, vous devez l'importer explicitement.

A la fin de very de votre fichier settings.py, ajoutez ceci:

try:
    from local_settings import *
except ImportError:
    pass

Le bloc try/except est là, de sorte que Python ignore simplement le cas où vous n'avez pas défini de fichier local_settings.

115
Daniel Roseman

C’est la meilleure pratique à mon avis:

  • local_settings importe de settings
  • local_settings remplace les paramètres spécifiques à l'environnement local, en particulier les variables DATABASES, SECRET_KEY, ALLOWED_HOSTS et DEBUG
  • passer aux commandes de gestion Django avec l'indicateur --settings=local_settings

Vous pouvez implémenter local_settings comme ceci:

from settings import *

DATABASES = {
    'default': {
        'ENGINE': 'Django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'Oracle'.
        'NAME': 'banco2',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'Host': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

Quelques points clés supplémentaires:

  • settings.py est en contrôle de version, écrit de manière à être prêt à être utilisé par les contributeurs
  • local_settings.py (ou plus généralement prod_settings.py) N'EST PAS dans le contrôle de version et est utilisé en production en spécifiant --settings=prod_settings ou similaire.

Toucher le moins possible le fichier de paramètres de stock facilite également la mise à niveau de votre version de Django. Lorsque vous mettez à niveau Django vers la version suivante, examinez le diff dans le stock settings.py et le vôtre, et prenez les mesures nécessaires en fonction de ce qui a changé. Les modifications des valeurs par défaut peuvent être importantes. Moins vous toucherez le fichier settings.py original, plus il sera facile de discerner les modifications en amont.

65
janos

Puisque le sujet refait surface régulièrement, permettez-moi de résumer pourquoi vous pourriez envisager cette approche:

  • un fichier de paramètres stupide est très rapide et facile à modifier; surtout dans un environnement de production. Aucun python requis: n'importe quel idiot peut intervenir et changer le mot de passe de la base de données dans un fichier qui ne contient que des noms et des valeurs; en particulier par rapport à un fichier de paramètres python complexe contenant de mystérieux noms dangereux BIGCAPS.

  • l'application settings doit être complètement séparée de l'application code. Vous pouvez placer un fichier config.ini en dehors de la racine du référentiel et ne plus jamais vous inquiéter d'un empotage entravant les réglages de vos paramètres personnels, ni de la pollution de celui-ci par le repo, ni de ce code astucieux de vos settings.py ne le rendant pas plus avantageux pour les autres .

Cela ne s'appliquera pas aux petits projets, mais sur des projets plus importants, j'ai conclu que la stratégie de configuration locale ne permettait pas de réduire les coûts. avec le temps, il y a assez de programmation d'applications qui rend difficile à gérer; principalement lorsque les paramètres deviennent dérivés et/ou codépendants. Il peut exister de bonnes raisons pour que les paramètres réagissent en fonction des paramètres locaux, ce qui oblige l’importation d’un fichier local_settings à remonter vers le milieu de settings.py. Je trouve que les choses commencent à devenir compliquées à mesure que cela se produit.

Ma solution actuelle consiste à utiliser un fichier config, je l’appelle "local.ini". Il ne contient que les valeurs qui changent réellement entre les instances déployées. Il n'y a pas de code: ce ne sont que des valeurs et des booléens:

[global]
domain = 127.0.0.1:8000
database_Host = 127.0.0.1
database_name = test_database
debug = Yes
google_analytics_id = UA-DEV-1
payments = testing
use_cdn = No

Grâce à cela, je peux traiter le settings.py comme n'importe quel autre code d'application: modifiez-le, archivez-le et déployez-le sans avoir à vous soucier de tester quel que soit le code dissimulé dans un code python local_settings. Mon settings.py est exempt de conditions de concurrence qui se présentent lorsque les paramètres ultérieurs dépendent des paramètres locaux, et je peux activer et désactiver les fonctionnalités pour écrire du code linéaire facile à suivre. Plus besoin de modifier à la hâte le fichier local_settings lorsque j'ai oublié d'ajouter une nouvelle valeur, et plus aucun fichier daves_local_settings.py et bobs_local_settings.py ne se glisse dans le référentiel.

from ConfigParser import RawConfigParser
parser = RawConfigParser()

APPLICATION_ROOT = path.abspath(path.dirname(__file__))
parser.readfp(open(path.join(APPLICATION_ROOT, 'local.ini')))

# simple variables
DATABASE_Host = parser.get('global', 'database_Host')
DATABASE_NAME = parser.get('global', 'database_name')

# interdependencies
from version import get_cdn_version
CDN = 'd99phdomw5k72k.cloudfront.net'
if parser.getboolean('global', 'use_cdn'):
    STATIC_URL = '/{}/static/{}/'.format(CDN, get_cdn_version())
else:
    STATIC_URL = '/static/'


# switches
payments = parser.get('global', 'payments')
if payments == 'testing':
    PAYMENT_GATEWAY_ENDPOINT = 'https://api.sandbox.gateway.com'
else:
    PAYMENT_GATEWAY_ENDPOINT = 'https://api.live.gateway.com'

Si vous rencontrez un BOFH , comme je l'avais déjà fait une fois, il était particulièrement enthousiasmé par la possibilité de coller le local.ini dans le répertoire /etc en tant que /etc/ourapp.ini et de conserver ainsi le répertoire de l'application proprement dit en tant qu'exportation de référentiel pur. Bien sûr, vous pouvez le faire avec un fichier local_settings.py mais la dernière chose qu’il souhaitait faire était de manipuler le code python. Un simple fichier de configuration qu'il pourrait manipuler.

10
John Mee

J'ai gardé une copie de __local_settings.py:

  • local_settings.py est ignoré dans le contrôle de version, mais pas __local_settings.py
  • mettre à jour README.md pour informer l'équipe de la configuration: cp {__,}local_settings.py (qui en crée une copie pour leurs paramètres local_settings)

Autrefois

J'avais l'habitude d'importer ces paramètres.

# settings.py
DATABASE = {...}

try:
    from .local_settings import *
except ImportError:
    pass

à présent

Je viens d'importer les paramètres à partir du local_settings.py

Et avec la commande suivante: python manage.py runserver --settings=<proj>.local_settings

# local_settings.py & __local_settings.py
from .settings import *

DATABASE = {...}

Et depuis, d'habitude, je n'interagis pas directement avec manage.py, car certains paramètres me sont explicitement nécessaires (par exemple, address:port). Par conséquent, je mets tous ces commandes dans ma Makefile.

Par exemple, voici mon Makefile:

run:
    python manage.py runserver 0.0.0.0:8000 --settings=<proj>.local_settings

sh:
    python manage.py Shell_plus --settings=<proj>.local_settings

dep:
    npm install
    pip install -r requirements.txt

Ainsi:

make dep
make sh 
make run

Conclusion

À condition que vous utilisiez non en utilisant Makefile comme flux de travail, vous pouvez utiliser la méthode précédente, mais si vous utilisez makefile, alors je pense qu'il est préférable d'être plus explicite dans votre Makefile. 

4
Yeo

Avant d’exécuter le serveur, faites

export Django_SETTINGS_MODULE=your_app_name.local_settings où your_app_name doit être remplacé par le nom de votre application . Et n'oublie pas de faire 

from settings import *

dans votre fichier local_settings.py

3
Siddhesh Suthar

Ajoutez ceci à la fin du fichier settings.py

try:
    from .local_settings import *
except ImportError:
    pass

Et créez le fichier local_settings.py avec vos nouveaux paramètres par exemple

DATABASES = {
    'default': {
        'ENGINE': 'Django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'Oracle'.
        'NAME': 'banco2',                      # Or path to database file if using sqlite3.
        'USER': 'root',                      # Not used with sqlite3.
        'PASSWORD': '123',                  # Not used with sqlite3.
        'Host': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}
0
Holovin

Une autre approche consiste à utiliser python-dotenv et des variables d’environnement pour personnaliser les paramètres de différents environnements. 

Créez le fichier .env à côté de votre settings.py:

# .env
SECRET_KEY=your-secret-key
DATABASE_PASSWORD=your-database-password

Ajoutez le code suivant à votre settings.py:

# settings.py
from dotenv import load_dotenv
load_dotenv()

# OR, explicitly providing path to '.env'
from pathlib import Path  # python 3.4+
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)

À ce stade, les clés/valeurs analysées du fichier .env sont présentes sous forme de variables d’environnement et sont facilement accessibles via os.getenv():

# settings.py
import os
SECRET_KEY = os.getenv('SECRET_KEY')
DATABASE_PASSWORD = os.getenv('DATABASE_PASSWORD')   
0
Eugene Yarmash

J'ai trouvé la solution similaire. Voici ma configuration pour ce cas:

settings.py:

DEBUG = False

try:
    from local_settings import *

except ImportError:
    pass

if DEBUG is False:
    ALLOWED_HOSTS = ['sth.com']
    DATABASES = {
        ....
    }

local_settings.py:

from settings import *
ALLOWED_HOSTS = ['*']
DEBUG = True
DATABASES = {
    ...
}
0
Darex1991