¿Cómo administrar la configuración local vs producción en Django?
¿Cuál es la forma recomendada de manejar la configuración para el desarrollo local y el servidor de producción? Algunos de ellos (como constantes, etc.) se pueden cambiar/acceder en ambos, pero algunos de ellos (como rutas a archivos estáticos) deben permanecer diferentes, y por lo tanto no deben sobrescribirse cada vez que se implemente el nuevo código.
Actualmente, estoy agregando todas las constantes a settings.py
. Pero cada vez que cambio alguna constante localmente, tengo que copiarla al servidor de producción y editar el archivo para cambios específicos de producción... :(
Editar: parece que no hay una respuesta estándar a esta pregunta, he aceptado el método más popular.
20 answers
En settings.py
:
try:
from local_settings import *
except ImportError as e:
pass
Puede anular lo que necesita en local_settings.py
; debe permanecer fuera de su control de versiones entonces. Pero ya que mencionas copiar, supongo que no usas ninguno;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-29 10:38:48
Dos cucharadas de Django: Mejores prácticas para Django 1.5 sugiere usar control de versiones para sus archivos de configuración y almacenar los archivos en un directorio separado:
project/
app1/
app2/
project/
__init__.py
settings/
__init__.py
base.py
local.py
production.py
manage.py
El archivo base.py
contiene configuraciones comunes (como MEDIA_ROOT o ADMIN), mientras que local.py
y production.py
tienen configuraciones específicas del sitio:
En el archivo base settings/base.py
:
INSTALLED_APPS = (
# common apps...
)
En el archivo de configuración de desarrollo local settings/local.py
:
from project.settings.base import *
DEBUG = True
INSTALLED_APPS += (
'debug_toolbar', # and other apps for local development
)
En el archivo archivo de configuración de producción settings/production.py
:
from project.settings.base import *
DEBUG = False
INSTALLED_APPS += (
# other apps for production site
)
Luego, cuando ejecuta django, agrega la opción --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
Los autores del libro también han puesto una plantilla de diseño de proyecto de muestra en Github.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 01:09:36
En lugar de settings.py
, utilice este diseño:
.
└── settings/
├── __init__.py <= not versioned
├── common.py
├── dev.py
└── prod.py
common.py
es donde vive la mayor parte de su configuración.
prod.py
importa todo de común, y anula lo que necesita para anular:
from __future__ import absolute_import # optional, but I like it
from .common import *
# Production overrides
DEBUG = False
#...
Del mismo modo, dev.py
importa todo desde common.py
y anula todo lo que necesita.
Finalmente, __init__.py
es donde decide qué configuración cargar, y también es donde almacena secretos (por lo tanto, este archivo no debe ser versioned):
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..."
Lo que me gusta de esta solución es:
- Todo está en su sistema de versiones, excepto secrets
- La mayor parte de la configuración está en un solo lugar:
common.py
. - Las cosas específicas de Prod entran
prod.py
, las cosas específicas de dev entrandev.py
. Es simple. - Puedes anular cosas de
common.py
enprod.py
odev.py
, y puedes anular cualquier cosa en__init__.py
. - Es python sencillo. No hay hacks de reimportación.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-09 19:48:26
Utilizo una versión ligeramente modificada del estilo de configuración "if DEBUG" que publicó Harper Shelby. Obviamente dependiendo del entorno (win/linux / etc.) el código podría necesitar ser ajustado un poco.
Yo estaba en el pasado usando el "si DEBUG", pero encontré que de vez en cuando necesitaba hacer pruebas con DEUBG establecido en False. Lo que realmente quería distinguir si el entorno era producción o desarrollo, lo que me dio la libertad de elegir el nivel de DEPURACIÓN.
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'
Todavía considere esta forma de configuración un trabajo en progreso. No he visto ninguna manera de manejar la configuración de Django que cubriera todas las bases y al mismo tiempo no fuera una molestia total para configurar (no estoy abajo con los métodos de archivos de configuración 5x).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-26 18:47:16
Utilizo un settings_local.py y a settings_production.py. Después de probar varias opciones he encontrado que es fácil perder el tiempo con soluciones complejas cuando simplemente tener dos archivos de configuración se siente fácil y rápido.
Cuando utiliza mod_python/mod_wsgi para su proyecto Django, debe apuntar a su archivo de configuración. Si lo apuntas a app/settings_local.py en su servidor local y app/settings_production.py en su servidor de producción, la vida se vuelve fácil. Solo tienes que editar el archivo de configuración y reinicie el servidor (Django development server se reiniciará automáticamente).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-26 18:12:30
Administro mis configuraciones con la ayuda de django-split-settings.
Es un reemplazo desplegable para la configuración predeterminada. Es simple, pero configurable. Y la refactorización de la configuración existente no es necesaria.
Aquí hay un pequeño ejemplo (archivo 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()
)
Eso es todo.
Actualizar
Escribí una entrada de blog sobre cómo administrar la configuración de django
con django-split-sttings
. ¡Echa un vistazo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-08 10:31:27
El problema con la mayoría de estas soluciones es que tiene sus configuraciones locales aplicadas antes de las comunes, o después de.
Así que es imposible anular cosas como
- la configuración específica de env define las direcciones para el grupo memcached, y en el archivo de configuración principal este valor se usa para configurar el backend de caché
- la configuración específica de env agrega o elimina aplicaciones / middleware a la predeterminada
En el a la misma hora.
Se puede implementar una solución usando archivos de configuración de estilo "ini"con la clase ConfigParser. Admite varios archivos, interpolación de cadenas perezosas, valores predeterminados y muchas otras ventajas. Una vez que se han cargado varios archivos, se pueden cargar más archivos y sus valores anularán los anteriores, si los hay.
Carga uno o más archivos de configuración, dependiendo de la dirección de la máquina, variables de entorno e incluso valores en archivos de configuración previamente cargados. Entonces solo tiene que utilizar los valores analizados para completar la configuración.
Una estrategia que he utilizado con éxito ha sido:
- Cargar un archivo predeterminado
defaults.ini
- Compruebe el nombre de la máquina y cargue todos los archivos que coincidan con el FQDN invertido, desde la coincidencia más corta hasta la más larga (por lo tanto, cargué
net.ini
, luegonet.domain.ini
, luegonet.domain.webserver01.ini
, cada uno posiblemente anulando los valores del anterior). Esta cuenta también para las máquinas de los desarrolladores, por lo que cada uno podría configurar su controlador de base de datos preferido, sucesivamente. para el desarrollo local - Compruebe si hay un" nombre de clúster " declarado, y en ese caso load
cluster.cluster_name.ini
, que puede definir cosas como IPS de base de datos y caché
Como ejemplo de algo que puede lograr con esto, puede definir un valor de "subdominio" por env, que luego se usa en la configuración predeterminada (como hostname: %(subdomain).whatever.net
) para definir todos los nombres de host necesarios y las cosas de cookies que django necesita para funcionar.
Esto es lo más SECO que pude conseguir, la mayoría de los archivos (existentes) tenían solo 3 o 4 configuración. Además de esto tuve que administrar la configuración del cliente, por lo que existía un conjunto adicional de archivos de configuración (con cosas como nombres de base de datos, usuarios y contraseñas, subdominio asignado, etc.), uno o más por cliente.
Uno puede escalar esto tan bajo o tan alto como sea necesario, simplemente ponga en el archivo de configuración las claves que desea configurar por entorno, y una vez que haya necesidad de una nueva configuración, ponga el valor anterior en la configuración predeterminada, y lo anule donde necesario.
Este sistema ha demostrado ser fiable y funciona bien con el control de versiones. Se ha utilizado durante mucho tiempo administrando dos clústeres de aplicaciones separados (15 o más instancias separadas del sitio de django por máquina), con más de 50 clientes, donde los clústeres cambiaban de tamaño y miembros dependiendo del estado de ánimo del administrador del sistema...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-01 14:18:02
Recuerde que settings.py es un archivo de código en vivo. Suponiendo que no tiene establecido un sistema de DEPURACIÓN en producción (lo cual es una práctica recomendada), puede hacer algo como:
if DEBUG:
STATIC_PATH = /path/to/dev/files
else:
STATIC_PATH = /path/to/production/files
Bastante básico, pero usted podría, en teoría, subir a cualquier nivel de complejidad basado solo en el valor de DEPURACIÓN - o cualquier otra variable o verificación de código que desee utilizar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-26 18:05:19
También estoy trabajando con Laravel y me gusta la implementación allí. Traté de imitarlo y combinarlo con la solución propuesta por T. Stone (ver arriba):
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
Tal vez algo como esto te ayudaría.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-04 08:38:05
Mi solución a ese problema es también una mezcla de algunas soluciones ya mencionadas aquí:
- Guardo un archivo llamado
local_settings.py
que tiene el contenidoUSING_LOCAL = True
en dev yUSING_LOCAL = False
en prod - En
settings.py
hago una importación de ese archivo para obtener la configuraciónUSING_LOCAL
Entonces baso todas mis configuraciones dependientes del entorno en esa:
DEBUG = USING_LOCAL
if USING_LOCAL:
# dev database settings
else:
# prod database settings
Prefiero esto a tener dos separados settings.py archivos que necesito mantener ya que puedo mantener mi configuración estructurada en un solo archivo más fácil que tenerlos repartidos en varios archivos. Así, cuando actualizo una configuración no me olvido de hacerlo para ambos entornos.
Por supuesto que cada método tiene sus desventajas y este no es una excepción. El problema aquí es que no puedo sobrescribir el archivo local_settings.py
cada vez que introduzco mis cambios en producción, lo que significa que no puedo copiar todos los archivos a ciegas, pero eso es algo con lo que puedo vivir.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-26 20:10:27
Para la mayoría de mis proyectos utilizo el siguiente patrón:
- Crear settings_base.py donde almaceno configuraciones que son comunes para todos los entornos
- Cada vez que necesito usar un nuevo entorno con requisitos específicos, creo un nuevo archivo de configuración (p. ej. settings_local.py) que hereda el contenido de settings_base.py y anula / agrega variables de configuración adecuadas (
from settings_base import *
)
(Para ejecutar manage.py con el archivo de configuración personalizado, simplemente use la opción de comando settings settings: manage.py <command> --settings=settings_you_wish_to_use.py
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-03 09:53:07
Utilizo una variación de lo que jpartogi mencionó anteriormente, que encuentro un poco más corta:
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)
Básicamente en cada equipo (desarrollo o producción) tengo el adecuado hostname_settings.py archivo que se carga dinámicamente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 19:48:52
También hay Ajustes de Django Classy. Personalmente soy un gran fan de ella. Está construido por una de las personas más activas en el IRC de Django. Usarías var del entorno para establecer las cosas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-21 17:56:20
TL;DR: El truco es modificar os.environment
antes de importar settings/base.py
en cualquier settings/<purpose>.py
, esto simplificará mucho las cosas.
Solo pensar en todos estos archivos entrelazados me da dolor de cabeza.
Combinar, importar (a veces condicionalmente), sobreescribir, parchear lo que ya estaba establecido en caso de que DEBUG
la configuración cambiara más adelante.
Qué pesadilla!
A través de los años pasé por todas las soluciones diferentes. Todos de alguna manera funcionan, pero son tan dolorosos de manejar.
¡WTF! ¿Realmente necesitamos toda esa molestia? Empezamos con un solo archivo settings.py
.
Ahora necesitamos una documentación solo para combinar correctamente todos estos juntos en un orden correcto!
Espero finalmente llegar al (mi) punto dulce con la solución a continuación.
Recapitulemos las metas (algunas comunes, otras mías) {[46]]}
Mantenga los secretos en secreto, no los almacene en un repositorio.
Establecer / leer claves y secretos a través de la configuración del entorno, 12 factor style .
Tener valores predeterminados de reserva sensatos. Lo ideal para el desarrollo local no necesita nada más aparte de los valores predeterminados.
...pero trate de mantener la producción predeterminada segura. Es mejor omitir una anulación de configuración localmente,
que tener que recordar para ajustar la configuración por defecto seguro para la producción.
Tener la capacidad de cambiar DEBUG
on/off de una manera que puede tener un efecto en otros ajustes (por ejemplo. usando javascript comprimido o ni).
Cambiar entre configuraciones de propósito, como local / testing/staging / production, debe basarse solo en DJANGO_SETTINGS_MODULE
, nada más.
...pero permitir más parametrización a través de ajustes de entorno como DATABASE_URL
.
...también les permiten utilizar diferentes configuraciones de propósito y ejecutarlos localmente uno al lado del otro, por ejemplo. configuración de producción en la máquina de desarrollo local, para acceder a la base de datos de producción o al estilo comprimido de prueba de humo hoja.
Fail si una variable de entorno no se establece explícitamente (requiere un valor vacío como mínimo), especialmente en producción, por ejemplo. EMAIL_HOST_PASSWORD
.
Responder al valor predeterminado DJANGO_SETTINGS_MODULE
establecido en manage.py durante django-admin startproject
Mantenga los condicionales al mínimo, si la condición es el tipo de entorno propuesto (eg. para el archivo de registro del conjunto de producción y su rotación), anule los ajustes en los ajustes propuestos asociados file.
No es{[46]]}
No permita que django lea la configuración DJANGO_SETTINGS_MODULE de un archivo.
Ugh! Piensa en lo meta que es esto. Si necesita tener un archivo (como docker
env) lea eso en el entorno antes de mirar un proceso de django.
No anule DJANGO_SETTINGS_MODULE en el código de su proyecto / aplicación, por ejemplo. basado en nombre de host o nombre de proceso.
Si usted es perezoso para establecer variable de entorno (como para setup.py test
) hacerlo en herramientas justo antes de ejecutar el código del proyecto.
Evite la magia y los parches de cómo django lee sus ajustes, preprocese los ajustes pero no interfiera después.
No hay lógica complicada basada en tonterías. La configuración debe ser fija y materializada, no computada sobre la marcha.
Proporcionar un valor predeterminado de reserva es suficiente lógica aquí.
¿Realmente desea depurar, por qué localmente tiene un conjunto correcto de configuraciones pero en producción en un servidor remoto,
en una de cien máquinas, ¿algo calculado de manera diferente? Oh! ¿Pruebas unitarias? ¿Para ajustes? ¿En serio?
Solución
Mantenga los secretos en secreto, no los almacene en un repositorio.
Establecer / leer claves y secretos a través de la configuración del entorno, 12 factor style .
Tener valores predeterminados de reserva sensatos. Lo ideal para el desarrollo local no necesita nada más aparte de los valores predeterminados.
...pero trate de mantener la producción predeterminada segura. Es mejor omitir una anulación de configuración localmente, que tener que recordar para ajustar la configuración por defecto seguro para la producción.
Tener la capacidad de cambiar DEBUG
on/off de una manera que puede tener un efecto en otros ajustes (por ejemplo. usando javascript comprimido o ni).
Cambiar entre configuraciones de propósito, como local / testing/staging / production, debe basarse solo en DJANGO_SETTINGS_MODULE
, nada más.
...pero permitir más parametrización a través de ajustes de entorno como DATABASE_URL
.
...también les permiten utilizar diferentes configuraciones de propósito y ejecutarlos localmente uno al lado del otro, por ejemplo. configuración de producción en la máquina de desarrollo local, para acceder a la base de datos de producción o al estilo comprimido de prueba de humo hoja.
Fail si una variable de entorno no se establece explícitamente (requiere un valor vacío como mínimo), especialmente en producción, por ejemplo. EMAIL_HOST_PASSWORD
.
Responder al valor predeterminado DJANGO_SETTINGS_MODULE
establecido en manage.py durante django-admin startproject
Mantenga los condicionales al mínimo, si la condición es el tipo de entorno propuesto (eg. para el archivo de registro del conjunto de producción y su rotación), anule los ajustes en los ajustes propuestos asociados file.
No permita que django lea la configuración DJANGO_SETTINGS_MODULE de un archivo.
Ugh! Piensa en lo meta que es esto. Si necesita tener un archivo (como docker env) lea eso en el entorno antes de mirar un proceso de django.No anule DJANGO_SETTINGS_MODULE en el código de su proyecto / aplicación, por ejemplo. basado en nombre de host o nombre de proceso.
Si usted es perezoso para establecer variable de entorno (como parasetup.py test
) hacerlo en herramientas justo antes de ejecutar el código del proyecto.Evite la magia y los parches de cómo django lee sus ajustes, preprocese los ajustes pero no interfiera después.
No hay lógica complicada basada en tonterías. La configuración debe ser fija y materializada, no computada sobre la marcha. Proporcionar un valor predeterminado de reserva es suficiente lógica aquí.
¿Realmente desea depurar, por qué localmente tiene un conjunto correcto de configuraciones pero en producción en un servidor remoto, en una de cien máquinas, ¿algo calculado de manera diferente? Oh! ¿Pruebas unitarias? ¿Para ajustes? ¿En serio?
Solución
Mi estrategia consiste en un excelente django-environ usado con archivos de estilo ini
,
proporcionar os.environment
valores predeterminados para el desarrollo local, algunos archivos settings/<purpose>.py
mínimos y cortos que tienen un
import settings/base.py
DESPUÉS de el os.environment
se estableció a partir de un archivo INI
. Esto efectivamente nos da una especie de inyección de configuración.
El truco aquí es modifique os.environment
antes de importar settings/base.py
.
Para ver el ejemplo completo ve a hacer el 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
Ajustes/.env
A por defecto para el desarrollo local. Un archivo secreto, para establecer principalmente las variables de entorno requeridas.
Establézcalos en valores vacíos si no son necesarios en el desarrollo local.
Proporcionamos valores predeterminados aquí y no en settings/base.py
para fallar en cualquier otra máquina si faltan en el ambiente.
Settings/local.py
Lo que sucede aquí, es cargar el entorno desde settings/.env
, luego importar la configuración común
de settings/base.py
. Después de eso podemos anular algunos para facilitar el desarrollo 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
Para la producción no debemos esperar un archivo de entorno, pero es más fácil tener uno si estamos probando algo.
Pero de todos modos, lest proporciona pocos valores predeterminados en línea, por lo que settings/base.py
puede responder en consecuencia.
environ.Env.read_env(Path(__file__) / "production.env", DEBUG='False', ASSETS_DEBUG='False')
from .base import *
El principal punto de interés aquí son DEBUG
y ASSETS_DEBUG
reemplaza,
se aplicarán a python os.environ
SOLO si faltan en el entorno y en el archivo.
Estos serán nuestros valores predeterminados de producción, no es necesario ponerlos en el entorno o archivo, pero se pueden sobrescribir si es necesario. ¡Genial!
Settings/base.py
Estos son los ajustes de django en su mayoría vanilla, con algunos condicionales y mucho de leerlos desde el entorno. Casi todo está aquí, manteniendo todos los entornos propuestos consistentes y lo más similares posible.
Las principales diferencias están a continuación (espero que sean auto explicativas):
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',)
El último bit muestra el poder aquí. ASSETS_DEBUG
tiene un defecto sensible,
que puede ser anulado en settings/production.py
e incluso que puede ser anulado por una configuración de entorno! Yay!
En efecto, tenemos una jerarquía mixta de importancia:
- settings/.py -establece los valores predeterminados basados en el propósito, no almacena secretos
- settings/base.py - está controlado principalmente por el medio ambiente
- configuración del entorno de proceso-12 factor baby!
- ajustes/.env - valores predeterminados locales para easy startup
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-15 11:45:33
Lo diferencio en manage.py y creó dos archivos de configuración separados: local_settings.py y prod_settings.py.
En manage.py Compruebo si el servidor es un servidor local o un servidor de producción. Si es un servidor local se cargaría local_settings.py y es un servidor de producción que cargaría prod_settings.py. Básicamente así es como se vería:
#!/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)
Me pareció más fácil separar el archivo de configuración en dos archivos separados en lugar de hacer un montón de ifs dentro del archivo de configuración.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-27 11:52:22
Como alternativa para mantener un archivo diferente si: Si está utilizando git o cualquier otro VCS para enviar códigos desde el local al servidor, lo que puede hacer es agregar el archivo de configuración .gitignore.
Esto te permitirá tener contenido diferente en ambos lugares sin ningún problema. Así que en el servidor se puede configurar una versión independiente de settings.py y cualquier cambio realizado en el local no se reflejará en el servidor y viceversa.
Además, eliminará la settings.py archivo desde github también, la gran culpa, que he visto muchos novatos haciendo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-03 06:15:30
Para usar una configuración settings
diferente en un entorno diferente, cree un archivo de configuración diferente. Y en el script de implementación, inicie el servidor usando --settings=<my-settings.py>
parámetro, a través del cual puede usar diferentes ajustes en diferentes entornos.
Beneficios de usar este enfoque :
-
La configuración será modular en función de cada entorno
Puede importar el
master_settings.py
que contiene la configuración base en elenvironmnet_configuration.py
y reemplazar los valores que desea cambiar en ese entorno.Si tiene un equipo enorme, cada desarrollador puede tener su propio
local_settings.py
que puede agregar al repositorio de código sin ningún riesgo de modificar la configuración del servidor. Puede agregar estas configuraciones locales a.gitnore
si usa git o.hginore
si Mercurialpara Control de versiones (o cualquier otro). De esa manera, la configuración local ni siquiera será la parte de la base de código real manteniéndola limpiar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 22:40:13
1 - Crear una nueva carpeta dentro de la aplicación y la configuración de nombre a la misma.
2-Ahora cree un nuevo archivo init.py en él y dentro de él escriba
from .base import *
try:
De .importación local *
except:
Pass
try:
De .producción importación *
except:
Pass
3-Crear tres nuevos archivos en la carpeta de configuración nombre local.py y production.py y base.py
4-Dentro base.py copia todo el contenido de la configuración anterior.p carpeta y cambiarle el nombre con algo diferente digamos old_settings.py
5-In base.py cambie su ruta BASE_DIR para que apunte a su nueva ruta de configuración
Old path-> BASE_DIR = os.camino.dirname (os.camino.dirname (os.camino.archivo abspath ()))
Nueva ruta -> BASE_DIR = os.camino.dirname (os.camino.dirname (os.camino.dirname (os.camino.archivo abspath ()))
Ahora de esta manera el dir del proyecto puede ser estructurado y manejable entre la producción y el desarrollo local.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-10 04:32:50
Tuve mi configuración dividida de la siguiente manera
settings/
|
|- base.py
|- dev.py
|- prod.py
Tenemos 3 ambientes
- dev
- estadificación
- producción
Ahora, obviamente, la puesta en escena y la producción deben tener el máximo entorno similar posible. Así que nos quedamos prod.py
para ambos.
Pero hubo un caso en el que tuve que identificar que el servidor en ejecución es un servidor de producción. La respuesta de @T. Stone me ayudó a escribir el cheque de la siguiente manera.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-12 16:39:47
Encontré las respuestas aquí muy útiles. (¿ Se ha resuelto esto de manera más definitiva? La última respuesta fue hace un año. Después de considerar todos los enfoques enumerados, se me ocurrió una solución que no vi en la lista aquí.
Mis criterios fueron:
- Todo debe estar en control de código fuente. No me gustan las cosas raras por ahí.
- Idealmente, mantenga la configuración en un archivo. Me olvido de las cosas si no estoy mirando a la derecha en ellos:)
- No hay ediciones manuales para desplegar. Debería ser capaz de probar / empujar / desplegar con un solo comando fabric.
- Evite filtrar los ajustes de desarrollo a la producción.
- Manténgase lo más cerca posible del diseño "estándar" (*tos*) de Django como sea posible.
Pensé que encender la máquina host tenía algún sentido, pero luego pensé que el verdadero problema aquí es diferentes configuraciones para diferentes entornos , y tuve un momento ajá. Puse este código al final de mi settings.py archivo:
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 esta manera, la aplicación establece por defecto la configuración de producción, lo que significa que está explícitamente "en la lista blanca" de su entorno de desarrollo. Es mucho más seguro olvidarse de establecer la variable de entorno localmente que si fuera al revés y se olvidara de establecer algo en producción y dejar que se usen algunas configuraciones de desarrollo.
Cuando se desarrolla localmente, ya sea desde el shell o en a .bash_profile o donde sea:
$ export DJANGO_DEVELOPMENT_SERVER=yep
(O si está desarrollando en Windows, configure a través del Panel de Control o como se llame en estos días... Windows siempre lo hacía tan oscuro que se podían establecer variables de entorno.)
Con este enfoque, los ajustes de desarrollo están todos en un lugar (estándar), y simplemente anulan los de producción donde sea necesario. Cualquier error con los ajustes de desarrollo debe ser completamente seguro para comprometerse con el control de la fuente sin impacto en la producción.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-17 06:49:49