Comment configurer Django pour un développement et un déploiement simples?

112

J'ai tendance à utiliser SQLite lorsque je fais du développement Django , mais sur un serveur live, quelque chose de plus robuste est souvent nécessaire ( MySQL / PostgreSQL , par exemple). Invariablement, il y a également d'autres changements à apporter aux paramètres de Django: différents emplacements / intensités de journalisation, chemins multimédias, etc.

Comment gérez-vous tous ces changements pour faire du déploiement un processus simple et automatisé?

Peter Mortensen
la source
Je ne fais rien d'aussi chic que quiconque apparemment :). Je profite juste de l'ORM fourni par django.
Andrew Sledge
1
La question était de savoir comment automatiser la modification des paramètres pour basculer entre les environnements :-)
Guruprasad
Vous pouvez jeter un oeil à ce paquet: django-split-settings
sobolevn

Réponses:

86

Mise à jour: django-configurations a été publié, ce qui est probablement une meilleure option pour la plupart des gens que de le faire manuellement.

Si vous préférez faire les choses manuellement, ma réponse précédente s'applique toujours:

J'ai plusieurs fichiers de paramètres.

  • settings_local.py - configuration spécifique à l'hôte, telle que le nom de la base de données, les chemins de fichiers, etc.
  • settings_development.py- configuration utilisée pour le développement, par exemple DEBUG = True.
  • settings_production.py- configuration utilisée pour la production, par exemple SERVER_EMAIL.

Je les lie tous ensemble avec un settings.pyfichier qui importe d'abord settings_local.py, puis l'un des deux autres. Il décide lequel charger par deux paramètres à l'intérieur settings_local.py- DEVELOPMENT_HOSTSet PRODUCTION_HOSTS. settings.pyappelle platform.node()pour trouver le nom d'hôte de la machine sur laquelle il s'exécute, puis recherche ce nom d'hôte dans les listes et charge le deuxième fichier de paramètres en fonction de la liste dans laquelle il trouve le nom d'hôte.

De cette façon, la seule chose dont vous devez vraiment vous soucier est de garder le settings_local.pyfichier à jour avec la configuration spécifique à l'hôte, et tout le reste est géré automatiquement.

Découvrez un exemple ici .

Jim
la source
2
et si la mise en scène (développement) et la production sont sur la même machine? platform.node () renvoie la même chose alors.
gwaramadze
2
L'exemple de lien est en panne.
Jickson
Excellente idée pour déterminer les paramètres en fonction des listes d'hôtes! Mon seul point critique est la nomenclature (settings_local.py est toujours importé en premier, donc tous les paramètres qui ne sont pas remplacés seront toujours actifs en production, ce qui rend le suffixe _localplutôt déroutant) et le fait que vous n'utilisez pas de modules (paramètres /base.py, settings / local.py, settings / production.py). Il serait également sage de conserver cela dans un référentiel séparé ... mieux encore, un service sécurisé qui sert ces informations à partir d'une source canonique (probablement exagérée pour la plupart) ... afin que le nouvel hôte ne nécessite pas une nouvelle version.
DylanYoung
Mieux encore, si vous utilisez un logiciel de gestion de machine, au lieu de vérifier la liste d'hôtes dans le .pyfichier et de donner ainsi à chaque hôte l'accès aux informations sur la configuration de tous les autres hôtes, vous pouvez créer un modèle de manage.py pour utiliser les paramètres appropriés fichier dans vos configurations de déploiement.
DylanYoung
26

Personnellement, j'utilise un seul settings.py pour le projet, je lui demande juste de rechercher le nom d'hôte sur lequel il se trouve (mes machines de développement ont des noms d'hôte qui commencent par "gabriel" donc j'ai juste ceci:

import socket
if socket.gethostname().startswith('gabriel'):
    LIVEHOST = False
else: 
    LIVEHOST = True

puis dans d'autres parties, j'ai des choses comme:

if LIVEHOST:
    DEBUG = False
    PREPEND_WWW = True
    MEDIA_URL = 'http://static1.grsites.com/'
else:
    DEBUG = True
    PREPEND_WWW = False
    MEDIA_URL = 'http://localhost:8000/static/'

etc. Un peu moins lisible, mais cela fonctionne bien et évite d'avoir à jongler avec plusieurs fichiers de paramètres.

Gabriel Ross
la source
J'aime cette idée, mais elle ne me permettra pas de différencier les différentes instances de Django exécutées sur le même hôte. Cela se produirait, par exemple, si vous aviez différentes instances exécutées pour différents sous-domaines sur le même hôte.
Erik
24

À la fin de settings.py, j'ai ce qui suit:

try:
    from settings_local import *
except ImportError:
    pass

De cette façon, si je veux remplacer les paramètres par défaut, je dois simplement placer settings_local.py juste à côté de settings.py.

Dmitry Shevchenko
la source
4
Ceci est légèrement dangereux car si une faute de frappe settings_localentraîne un ImportError, cela exceptva l'avaler en silence.
Chris Martin
Vous pouvez vérifier le message No module named...vs cannot import name..., mais il est fragile. Ou, placez vos importations dans settings_local.py dans try blocks et soulevez une exception plus spécifique: MisconfiguredSettingsou quelque chose dans ce sens.
DylanYoung
11

J'ai deux fichiers. settings_base.pyqui contient les paramètres communs / par défaut et qui est archivé dans le contrôle de code source. Chaque déploiement a un autre settings.py, qui s'exécute from settings_base import *au début, puis remplace si nécessaire.

John Millikin
la source
1
J'utilise ça aussi. Il est supérieur à l'inverse (dmishe "from settings_local import *" à la fin de settings.py) car il permet aux paramètres locaux d'accéder et de modifier les paramètres globaux si nécessaire.
Carl Meyer
3
Si settings_local.pytel est le cas from settings import *, il peut remplacer les valeurs dans settings.py. (le settings_local.pyfichier doit être importé à la fin de settings.py).
Seth le
Cela peut être fait de toute façon. Jetez un œil à stackoverflow.com/a/7047633/3124256 ci-dessus. @Seth C'est une recette pour une importation circulaire.
DylanYoung
7

Le moyen le plus simple que j'ai trouvé était:

1) utilisez les paramètres par défaut.py pour le développement local et 2) créez un fichier production-settings.py commençant par:

import os
from settings import *

Et puis remplacez simplement les paramètres qui diffèrent en production:

DEBUG = False
TEMPLATE_DEBUG = DEBUG


DATABASES = {
    'default': {
           ....
    }
}
André Bossard
la source
Comment django sait-il charger les paramètres de production?
AlxVallejo
2

Un peu lié, pour le problème du déploiement de Django lui-même avec plusieurs bases de données, vous voudrez peut-être jeter un œil à Djangostack . Vous pouvez télécharger un programme d'installation entièrement gratuit qui vous permet d'installer Apache, Python, Django, etc. Dans le cadre du processus d'installation, nous vous permettons de sélectionner la base de données que vous souhaitez utiliser (MySQL, SQLite, PostgreSQL). Nous utilisons beaucoup les installateurs lors de l'automatisation des déploiements en interne (ils peuvent être exécutés en mode sans assistance).

Josue
la source
1
Sinon, je voudrais recommander Django Turnkey Linux basé sur une pile Ubuntu * NIX avec django préinstallé.
jochem
1

J'ai mon fichier settings.py dans un répertoire externe. De cette façon, il n'est pas archivé dans le contrôle de code source ou écrasé par un déploiement. Je mets ceci dans le fichier settings.py sous mon projet Django, avec tous les paramètres par défaut:

import sys
import os.path

def _load_settings(path):    
    print "Loading configuration from %s" % (path)
    if os.path.exists(path):
    settings = {}
    # execfile can't modify globals directly, so we will load them manually
    execfile(path, globals(), settings)
    for setting in settings:
        globals()[setting] = settings[setting]

_load_settings("/usr/local/conf/local_settings.py")

Remarque: Ceci est très dangereux si vous ne pouvez pas faire confiance à local_settings.py.

Chase Seibert
la source
1

En plus des multiples fichiers de paramètres mentionnés par Jim, j'ai également tendance à placer deux paramètres dans mon fichier settings.py en haut BASE_DIRet à BASE_URLdéfinir le chemin du code et l'URL vers la base du site, tous les autres paramètres sont modifiés pour s'y ajouter.

BASE_DIR = "/home/sean/myapp/" par exemple MEDIA_ROOT = "%smedia/" % BASEDIR

Ainsi, lors du déplacement du projet, je n'ai qu'à modifier ces paramètres et non à rechercher l'ensemble du fichier.

Je recommanderais également de regarder fabric et Capistrano (outil Ruby, mais il peut être utilisé pour déployer des applications Django) qui facilitent l'automatisation du déploiement à distance.

Sean O Donnell
la source
Ansible est python et offre des fonctionnalités de provisionnement beaucoup plus robustes que Fabric. Ils se marient bien aussi.
DylanYoung
1

Eh bien, j'utilise cette configuration:

À la fin de settings.py:

#settings.py
try:
    from locale_settings import *
except ImportError:
    pass

Et dans locale_settings.py:

#locale_settings.py
class Settings(object):

    def __init__(self):
        import settings
        self.settings = settings

    def __getattr__(self, name):
        return getattr(self.settings, name)

settings = Settings()

INSTALLED_APPS = settings.INSTALLED_APPS + (
    'gunicorn',)

# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings
sacabuche
la source
1

Tant de réponses compliquées!

Chaque fichier settings.py est livré avec:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

J'utilise ce répertoire pour définir la variable DEBUG comme ceci (remplacez-le avec le directoy où se trouve votre code de développement):

DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
    DEBUG = True

Ensuite, chaque fois que le fichier settings.py est déplacé, DEBUG sera False et c'est votre environnement de production.

Chaque fois que vous avez besoin de paramètres différents de ceux de votre environnement de développement, utilisez simplement:

if(DEBUG):
    #Debug setting
else:
    #Release setting
JM Desrosiers
la source
0

Je pense que cela dépend de la taille du site pour savoir si vous devez abandonner l'utilisation de SQLite, j'ai utilisé avec succès SQLite sur plusieurs sites en direct plus petits et il fonctionne très bien.

Ycros
la source
0

J'utilise l'environnement:

if os.environ.get('WEB_MODE', None) == 'production' :
   from settings_production import *
else :
   from settings_dev import *

Je pense que c'est une bien meilleure approche, car vous aurez éventuellement besoin de paramètres spéciaux pour votre environnement de test, et vous pouvez facilement l'ajouter à cette condition.

slashmili
la source
0

C'est un article plus ancien, mais je pense que si j'ajoute cela utile, librarycela simplifiera les choses.

Utilisez django-configuration

Démarrage rapide

pip install django-configurations

Ensuite, sous-classez la classe configurations.Configuration incluse dans le fichier settings.py de votre projet ou dans tout autre module que vous utilisez pour stocker les constantes de paramètres, par exemple:

# mysite/settings.py

from configurations import Configuration

class Dev(Configuration):
    DEBUG = True

Définissez la DJANGO_CONFIGURATIONvariable d'environnement sur le nom de la classe que vous venez de créer, par exemple dans ~/.bashrc:

export DJANGO_CONFIGURATION=Dev

et la DJANGO_SETTINGS_MODULEvariable d'environnement vers le chemin d'importation du module comme d'habitude, par exemple dans bash:

export DJANGO_SETTINGS_MODULE=mysite.settings

Vous pouvez également fournir l' --configurationoption lors de l'utilisation des commandes de gestion Django le long des lignes de l' --settingsoption de ligne de commande par défaut de Django, par exemple:

python manage.py runserver --settings=mysite.settings --configuration=Dev

Pour permettre à Django d'utiliser votre configuration, vous devez maintenant modifier votre script manage.py ou wsgi.py pour utiliser les versions de django-configurations des fonctions de démarrage appropriées, par exemple un manage.py typique utilisant django-configurations ressemblerait à ceci:

#!/usr/bin/env python

import os
import sys

if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
    os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')

    from configurations.management import execute_from_command_line

    execute_from_command_line(sys.argv)

Remarquez à la ligne 10 que nous n'utilisons pas l'outil commun django.core.management.execute_from_command_linemais à la place configurations.management.execute_from_command_line.

La même chose s'applique à votre fichier wsgi.py , par exemple:

import os

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')

from configurations.wsgi import get_wsgi_application

application = get_wsgi_application()

Ici, nous n'utilisons pas la django.core.wsgi.get_wsgi_applicationfonction par défaut mais à la place configurations.wsgi.get_wsgi_application.

C'est tout! Vous pouvez maintenant utiliser votre projet avec manage.py et votre serveur compatible WSGI préféré.

Petit Phild
la source
-2

En fait, vous devriez probablement envisager d'avoir les mêmes (ou presque les mêmes) configurations pour votre environnement de développement et de production. Sinon, des situations comme "Hé, ça marche sur ma machine" se produiront de temps en temps.

Donc, pour automatiser votre déploiement et éliminer ces problèmes WOMM, utilisez simplement Docker .

Dmitrii Mikhailov
la source