Come si configura Django per lo sviluppo e la distribuzione semplici?


112

Tendo a usare SQLite quando eseguo lo sviluppo di Django , ma su un server live è spesso necessario qualcosa di più robusto ( MySQL / PostgreSQL , per esempio). Invariabilmente, ci sono anche altre modifiche da apportare alle impostazioni di Django: diverse posizioni / intensità di registrazione, percorsi multimediali, ecc.

Come gestisci tutte queste modifiche per rendere l'implementazione un processo semplice e automatizzato?


Non faccio niente di così stravagante come chiunque altro apparentemente :). Approfitto solo dell'ORM fornito da Django.
Andrew Sledge

1
La domanda era su come automatizzare la modifica delle impostazioni per passare da un ambiente all'altro :-)
Guruprasad


Puoi dare un'occhiata a questo pacchetto: django-split-settings
sobolevn

Risposte:


86

Aggiornamento: è stato rilasciato django-configurations che è probabilmente un'opzione migliore per la maggior parte delle persone rispetto a farlo manualmente.

Se preferisci fare le cose manualmente, la mia risposta precedente è ancora valida:

Ho più file di impostazioni.

  • settings_local.py - configurazione specifica dell'host, come nome del database, percorsi dei file, ecc.
  • settings_development.py- configurazione utilizzata per lo sviluppo, es DEBUG = True.
  • settings_production.py- configurazione utilizzata per la produzione, es SERVER_EMAIL.

Li lego tutti insieme con un settings.pyfile che importa prima settings_local.pye poi uno degli altri due. Decide quale caricare con due impostazioni all'interno settings_local.py- DEVELOPMENT_HOSTSe PRODUCTION_HOSTS. settings.pychiama platform.node()per trovare il nome host della macchina su cui è in esecuzione, quindi cerca quel nome host negli elenchi e carica il secondo file di impostazioni a seconda dell'elenco in cui trova il nome host.

In questo modo, l'unica cosa di cui devi davvero preoccuparti è mantenere il settings_local.pyfile aggiornato con la configurazione specifica dell'host e tutto il resto viene gestito automaticamente.

Guarda un esempio qui .


2
e se la messa in scena (sviluppo) e la produzione fossero sulla stessa macchina? platform.node () restituisce lo stesso allora.
gwaramadze

2
Il collegamento di esempio non è attivo.
Jickson

Ottima idea per determinare le selezioni in base agli elenchi di host! Il mio unico problema è la nomenclatura (settings_local.py viene sempre importato per primo, quindi tutte le impostazioni che non sono sovrascritte, saranno comunque attive in produzione, rendendo il suffisso _localpiuttosto confuso) e il fatto che non stai utilizzando moduli (impostazioni /base.py, settings / local.py, settings / production.py). Sarebbe anche saggio tenerlo in un repository separato ... meglio ancora, un servizio sicuro che fornisce queste informazioni da una fonte canonica (probabilmente eccessiva per la maggior parte) ... in modo che il nuovo host non richieda una nuova versione.
DylanYoung

Ancora meglio, se stai utilizzando un software di gestione della macchina, invece di controllare l'elenco degli host nel .pyfile, e quindi dare a ogni host l'accesso alle informazioni sulla configurazione di ogni altro host, puoi modellare il file manage.py per utilizzare le impostazioni appropriate file nelle configurazioni di distribuzione.
DylanYoung

26

Personalmente, utilizzo un singolo settings.py per il progetto, devo solo cercare il nome host su cui si trova (le mie macchine di sviluppo hanno nomi host che iniziano con "gabriel" quindi ho solo questo:

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

poi in altre parti ho cose come:

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/'

e così via. Un po 'meno leggibile, ma funziona bene e evita di dover manipolare più file di impostazioni.


Mi piace questa idea, ma non mi permetterà di distinguere tra diverse istanze di Django in esecuzione sullo stesso host. Ciò accadrebbe, ad esempio, se avessi istanze diverse in esecuzione per sottodomini diversi sullo stesso host.
Erik

24

Alla fine di settings.py ho quanto segue:

try:
    from settings_local import *
except ImportError:
    pass

In questo modo, se voglio sovrascrivere le impostazioni predefinite, devo semplicemente mettere settings_local.py accanto a settings.py.


4
Questo è leggermente pericoloso perché se un errore di battitura settings_localrisulta in un errore ImportError, questo exceptlo inghiottirà silenziosamente.
Chris Martin

Potresti controllare il messaggio No module named...vs cannot import name..., ma è fragile. Oppure, metti le tue importazioni in settings_local.py nei blocchi try e solleva un'eccezione più specifica: MisconfiguredSettingso qualcosa in tal senso.
DylanYoung

11

Ho due file. settings_base.pyche contiene impostazioni comuni / predefinite e che viene archiviato nel controllo del codice sorgente. Ogni distribuzione ha una distribuzione separata settings.py, che viene eseguita from settings_base import *all'inizio e quindi sostituita secondo necessità.


1
Lo uso anche io. È superiore all'inverso (dmishe "from settings_local import *" alla fine di settings.py) perché consente alle impostazioni locali di accedere e modificare quelle globali se necessario.
Carl Meyer

3
In settings_local.pytal caso from settings import *, può sovrascrivere i valori in settings.py. (il settings_local.pyfile deve essere importato alla fine di settings.py).
Seth

Questo può essere fatto comunque. Dai un'occhiata a stackoverflow.com/a/7047633/3124256 sopra. @Seth Questa è una ricetta per un'importazione circolare.
DylanYoung

7

Il modo più semplicistico che ho trovato è stato:

1) usa il file settings.py predefinito per lo sviluppo locale e 2) crea un production-settings.py che inizia con:

import os
from settings import *

E quindi sovrascrivi le impostazioni che differiscono nella produzione:

DEBUG = False
TEMPLATE_DEBUG = DEBUG


DATABASES = {
    'default': {
           ....
    }
}

Come fa Django a sapere come caricare le impostazioni di produzione?
AlxVallejo

2

Un po 'correlato, per il problema della distribuzione di Django stesso con più database, potresti voler dare un'occhiata a Djangostack . Puoi scaricare un programma di installazione completamente gratuito che ti consente di installare Apache, Python, Django, ecc. Come parte del processo di installazione, ti permettiamo di selezionare il database che desideri utilizzare (MySQL, SQLite, PostgreSQL). Utilizziamo ampiamente i programmi di installazione durante l'automazione delle distribuzioni internamente (possono essere eseguiti in modalità automatica).


1
In alternativa, vorrei raccomandare Django Turnkey Linux basato su uno stack Ubuntu * NIX con django preinstallato.
jochem

1

Ho il mio file settings.py in una directory esterna. In questo modo, non viene archiviato nel controllo del codice sorgente o sovrascritto da una distribuzione. Lo metto nel file settings.py sotto il mio progetto Django, insieme a qualsiasi impostazione predefinita:

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")

Nota: questo è molto pericoloso se non puoi fidarti di local_settings.py.


1

Oltre ai file di impostazioni multiple menzionati da Jim, tendo anche a inserire due impostazioni nel mio file settings.py in alto BASE_DIRe BASE_URLimpostare il percorso del codice e l'URL alla base del sito, tutte le altre impostazioni vengono modificate per aggiungersi a questi.

BASE_DIR = "/home/sean/myapp/" per esempio MEDIA_ROOT = "%smedia/" % BASEDIR

Quindi, quando sposto il progetto, devo solo modificare queste impostazioni e non cercare l'intero file.

Consiglierei anche di guardare fabric e Capistrano (strumento Ruby, ma può essere utilizzato per distribuire applicazioni Django) che facilitano l'automazione della distribuzione remota.


Ansible è Python e offre funzionalità di provisioning molto più robuste rispetto a Fabric. Anche loro si accoppiano bene.
DylanYoung

1

Bene, io uso questa configurazione:

Alla fine di settings.py:

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

E in 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

1

Tante risposte complicate!

Ogni file settings.py viene fornito con:

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

Uso quella directory per impostare la variabile DEBUG in questo modo (riposiziona con la directory dove si trova il tuo codice dev):

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

Quindi, ogni volta che il file settings.py viene spostato, DEBUG sarà False ed è il tuo ambiente di produzione.

Ogni volta che hai bisogno di impostazioni diverse da quelle nel tuo ambiente di sviluppo, usa:

if(DEBUG):
    #Debug setting
else:
    #Release setting

0

Penso che dipenda dalle dimensioni del sito se è necessario passare dall'utilizzo di SQLite, ho utilizzato con successo SQLite su diversi siti live più piccoli e funziona alla grande.


0

Uso l'ambiente:

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

Credo che questo sia un approccio molto migliore, perché alla fine hai bisogno di impostazioni speciali per il tuo ambiente di test e puoi facilmente aggiungerlo a questa condizione.


0

Questo è un post più vecchio ma penso che se aggiungo questo utile librarysemplificherà le cose.

Usa django-configuration

Avvio rapido

pip install django-configurations

Quindi sottoclasse la classe configurations.Configuration inclusa nel file settings.py del tuo progetto o qualsiasi altro modulo che stai utilizzando per memorizzare le costanti delle impostazioni, ad esempio:

# mysite/settings.py

from configurations import Configuration

class Dev(Configuration):
    DEBUG = True

Imposta la DJANGO_CONFIGURATIONvariabile d'ambiente sul nome della classe appena creata, ad esempio in ~/.bashrc:

export DJANGO_CONFIGURATION=Dev

e la DJANGO_SETTINGS_MODULEvariabile di ambiente nel percorso di importazione del modulo come al solito, ad esempio in bash:

export DJANGO_SETTINGS_MODULE=mysite.settings

In alternativa, fornire l' --configurationopzione quando si utilizzano i comandi di gestione di Django sulla falsariga --settingsdell'opzione della riga di comando predefinita di Django , ad esempio:

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

Per consentire a Django di utilizzare la tua configurazione ora devi modificare il tuo script manage.py o wsgi.py per utilizzare le versioni di django-configurations delle funzioni di avvio appropriate, ad esempio un tipico manage.py che utilizza django-configurations sarebbe simile a questo:

#!/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)

Notare che nella riga 10 non usiamo lo strumento comune django.core.management.execute_from_command_linema invece configurations.management.execute_from_command_line.

Lo stesso vale per il tuo file wsgi.py , ad esempio:

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()

Qui non usiamo la django.core.wsgi.get_wsgi_applicationfunzione predefinita ma invece configurations.wsgi.get_wsgi_application.

Questo è tutto! Ora puoi utilizzare il tuo progetto con manage.py e il tuo server abilitato WSGI preferito.


-2

In effetti dovresti probabilmente considerare di avere le stesse (o quasi le stesse) configurazioni per il tuo ambiente di sviluppo e produzione. In caso contrario, di tanto in tanto si verificheranno situazioni come "Ehi, funziona sulla mia macchina".

Quindi, per automatizzare la distribuzione ed eliminare quei problemi di WOMM, usa semplicemente Docker .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.