¿Cómo se configura Django para un desarrollo y una implementación simples?

112

Tiendo a usar SQLite cuando desarrollo Django , pero en un servidor en vivo a menudo se necesita algo más robusto ( MySQL / PostgreSQL , por ejemplo). Invariablemente, también hay otros cambios que realizar en la configuración de Django: diferentes ubicaciones / intensidades de registro, rutas de medios, etc.

¿Cómo gestiona todos estos cambios para que la implementación sea un proceso simple y automatizado?

Peter Mortensen
fuente
No hago nada tan elegante como cualquier otra persona aparentemente :). Simplemente aprovecho el ORM que proporciona django.
Andrew Sledge
1
La pregunta era cómo automatizar el cambio de configuración para cambiar entre entornos :-)
Guruprasad
Puede echar un vistazo a este paquete: django-split-settings
sobolevn

Respuestas:

86

Actualización: se ha lanzado django-configurations, que probablemente sea una mejor opción para la mayoría de las personas que hacerlo manualmente.

Si prefiere hacer las cosas manualmente, mi respuesta anterior aún se aplica:

Tengo varios archivos de configuración.

  • settings_local.py - configuración específica del host, como nombre de la base de datos, rutas de archivo, etc.
  • settings_development.py- configuración utilizada para el desarrollo, por ejemplo DEBUG = True.
  • settings_production.py- configuración utilizada para la producción, p SERVER_EMAIL. ej .

Ato todo esto junto con un settings.pyarchivo que primero importa settings_local.py, y luego uno de los otros dos. Decide cuál cargar mediante dos configuraciones internas settings_local.py: DEVELOPMENT_HOSTSy PRODUCTION_HOSTS. settings.pyllamadas platform.node()para encontrar el nombre de host de la máquina en la que se está ejecutando, y luego busca ese nombre de host en las listas y carga el segundo archivo de configuración según la lista en la que encuentre el nombre de host.

De esa manera, lo único de lo que realmente debe preocuparse es mantener el settings_local.pyarchivo actualizado con la configuración específica del host, y todo lo demás se maneja automáticamente.

Mira un ejemplo aquí .

Jim
fuente
2
¿Qué pasa si la puesta en escena (desarrollo) y la producción están en la misma máquina? platform.node () devuelve lo mismo entonces.
gwaramadze
2
El enlace de ejemplo está inactivo.
Jickson
¡Gran idea para determinar la configuración basada en listas de anfitriones! Mi único detalle es la nomenclatura (settings_local.py siempre se importa primero, por lo que cualquier configuración que no se anule, seguirá estando activa en producción, lo que hace que el sufijo sea _localbastante confuso) y el hecho de que no está utilizando módulos (settings /base.py, settings / local.py, settings / production.py). También sería prudente mantener esto en un repositorio separado ... mejor aún, un servicio seguro que proporcione esta información desde una fuente canónica (probablemente exagerada para la mayoría) ... para que el nuevo host no requiera una nueva versión.
DylanYoung
Aún mejor, si está utilizando un software de administración de máquinas, en lugar de verificar la lista de hosts en el .pyarchivo y, por lo tanto, dar acceso a cada host a la información sobre la configuración de todos los demás hosts, puede crear una plantilla del manage.py para usar la configuración adecuada. archivo en sus configuraciones de implementación.
DylanYoung
26

Personalmente, uso un archivo settings.py único para el proyecto, solo lo hago buscar el nombre de host en el que se encuentra (mis máquinas de desarrollo tienen nombres de host que comienzan con "gabriel", así que solo tengo esto:

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

luego en otras partes tengo cosas como:

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

y así. Un poco menos legible, pero funciona bien y evita tener que hacer malabares con varios archivos de configuración.

Gabriel Ross
fuente
Me gusta esta idea, pero no me permitirá diferenciar entre diferentes instancias de Django que se ejecutan en el mismo host. Esto sucedería, por ejemplo, si tuviera diferentes instancias ejecutándose para diferentes subdominios en el mismo host.
Erik
24

Al final de settings.py tengo lo siguiente:

try:
    from settings_local import *
except ImportError:
    pass

De esta manera, si quiero anular la configuración predeterminada, solo necesito poner settings_local.py justo al lado de settings.py.

Dmitry Shevchenko
fuente
4
Esto es un poco peligroso porque si un error tipográfico settings_localda como resultado un ImportError, este exceptse lo tragará en silencio.
Chris Martin
Puede comprobar el mensaje No module named...vs cannot import name..., pero es frágil. O coloque sus importaciones en settings_local.py en bloques de prueba y genere una excepción más específica: MisconfiguredSettingso algo por el estilo.
DylanYoung
11

Tengo dos archivos. settings_base.pyque contiene configuraciones comunes / predeterminadas, y que se registra en el control de fuente. Cada implementación tiene una implementación separada settings.py, que se ejecuta from settings_base import *al principio y luego se anula según sea necesario.

John Millikin
fuente
1
Yo también uso esto. Es superior a la inversa (dmishe's "from settings_local import *" al final de settings.py) porque permite que las configuraciones locales accedan y modifiquen las globales si es necesario.
Carl Meyer
3
Si settings_local.pyhace esto from settings import *, puede anular los valores en settings.py. (el settings_local.pyarchivo debe importarse al final de settings.py).
Seth
Eso se puede hacer de todos modos. Eche un vistazo a stackoverflow.com/a/7047633/3124256 arriba. @Seth Esa es una receta para una importación circular.
DylanYoung
7

La forma más simplista que encontré fue:

1) use el settings.py predeterminado para el desarrollo local y 2) cree un production-settings.py comenzando con:

import os
from settings import *

Y luego simplemente anule las configuraciones que difieren en la producción:

DEBUG = False
TEMPLATE_DEBUG = DEBUG


DATABASES = {
    'default': {
           ....
    }
}
Andre Bossard
fuente
¿Cómo sabe django cargar la configuración de producción?
AlxVallejo
2

Algo relacionado, para el problema de la implementación de Django con múltiples bases de datos, es posible que desee echar un vistazo a Djangostack . Puedes descargar un instalador completamente gratuito que te permite instalar Apache, Python, Django, etc. Como parte del proceso de instalación te permitimos seleccionar qué base de datos quieres usar (MySQL, SQLite, PostgreSQL). Usamos los instaladores ampliamente cuando automatizamos implementaciones internamente (se pueden ejecutar en modo desatendido).

Josué
fuente
1
Alternativamente, me gustaría recomendar Django Turnkey Linux basado en una pila Ubuntu * NIX con django preinstalado.
jochem
1

Tengo mi archivo settings.py en un directorio externo. De esa manera, no se registra en el control de código fuente ni se sobrescribe con una implementación. Puse esto en el archivo settings.py en mi proyecto Django, junto con cualquier configuración predeterminada:

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: Esto es muy peligroso si no puede confiar en local_settings.py.

Chase Seibert
fuente
1

Además de los múltiples archivos de configuración mencionados por Jim, también tiendo a colocar dos configuraciones en mi archivo settings.py en la parte superior BASE_DIRy BASE_URLestablecer la ruta del código y la URL a la base del sitio, todas las demás configuraciones se modifican para anexarse ​​a estos.

BASE_DIR = "/home/sean/myapp/" p.ej MEDIA_ROOT = "%smedia/" % BASEDIR

Entonces, cuando muevo el proyecto, solo tengo que editar esta configuración y no buscar en todo el archivo.

También recomendaría mirar fabric y Capistrano (herramienta Ruby, pero se puede usar para implementar aplicaciones Django) que facilitan la automatización de la implementación remota.

Sean O Donnell
fuente
Ansible es Python y ofrece instalaciones de aprovisionamiento mucho más sólidas que Fabric. También combinan muy bien.
DylanYoung
1

Bueno, uso esta configuración:

Al final de settings.py:

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

Y en 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
fuente
1

¡Tantas respuestas complicadas!

Cada archivo settings.py viene con:

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

Utilizo ese directorio para configurar la variable DEBUG de esta manera (reemplace con el directorio donde está su código de desarrollo):

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

Luego, cada vez que se mueva el archivo settings.py, DEBUG será False y será su entorno de producción.

Cada vez que necesite configuraciones diferentes a las de su entorno de desarrollo, simplemente use:

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

Creo que depende del tamaño del sitio si necesita dejar de usar SQLite, he usado SQLite con éxito en varios sitios en vivo más pequeños y funciona muy bien.

Ycros
fuente
0

Yo uso medio ambiente:

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

Creo que este es un enfoque mucho mejor, porque eventualmente necesitará configuraciones especiales para su entorno de prueba y puede agregarlo fácilmente a esta condición.

slashmili
fuente
0

Esta es una publicación más antigua, pero creo que si agrego esta útil library, simplificará las cosas.

Usa la configuración de django

Inicio rápido

pip install django-configurations

Luego, realice una subclase de las configuraciones incluidas. Clase de configuración en el archivo settings.py de su proyecto o cualquier otro módulo que esté utilizando para almacenar las constantes de configuración, por ejemplo:

# mysite/settings.py

from configurations import Configuration

class Dev(Configuration):
    DEBUG = True

Establezca la DJANGO_CONFIGURATIONvariable de entorno con el nombre de la clase que acaba de crear, por ejemplo, en ~/.bashrc:

export DJANGO_CONFIGURATION=Dev

y la DJANGO_SETTINGS_MODULEvariable de entorno a la ruta de importación del módulo como de costumbre, por ejemplo, en bash:

export DJANGO_SETTINGS_MODULE=mysite.settings

Alternativamente, proporcione la --configurationopción cuando use comandos de administración de Django siguiendo las líneas de la --settingsopción de línea de comandos predeterminada de Django , por ejemplo:

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

Para permitir que Django use su configuración, ahora tiene que modificar su script manage.py o wsgi.py para usar las versiones de django-configurations de las funciones de inicio apropiadas, por ejemplo, un manage.py típico usando django-configurations se vería así:

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

Observe que en la línea 10 no usamos la herramienta común, django.core.management.execute_from_command_linesino que configurations.management.execute_from_command_line.

Lo mismo se aplica a su archivo wsgi.py , por ejemplo:

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

Aquí no usamos la django.core.wsgi.get_wsgi_applicationfunción predeterminada , sino configurations.wsgi.get_wsgi_application.

¡Eso es! Ahora puede usar su proyecto con manage.py y su servidor habilitado para WSGI favorito.

Pequeño phild
fuente
-2

De hecho, probablemente debería considerar tener las mismas (o casi las mismas) configuraciones para su entorno de desarrollo y producción. De lo contrario, situaciones como "Oye, funciona en mi máquina" ocurrirán de vez en cuando.

Entonces, para automatizar su implementación y eliminar esos problemas de WOMM, simplemente use Docker .

Dmitrii Mikhailov
fuente