Como você configura o Django para desenvolvimento e implantação simples?

112

Eu costumo usar SQLite ao fazer desenvolvimento em Django , mas em um servidor ativo, algo mais robusto geralmente é necessário ( MySQL / PostgreSQL , por exemplo). Invariavelmente, há outras mudanças a serem feitas nas configurações do Django: diferentes locais / intensidades de registro, caminhos de mídia, etc.

Como você gerencia todas essas mudanças para tornar a implantação um processo simples e automatizado?

Peter Mortensen
fonte
Eu não faço nada tão sofisticado quanto qualquer outra pessoa aparentemente :). Acabei de tirar proveito do ORM que o django fornece.
Andrew Sledge,
1
A questão era como automatizar a alteração das configurações para alternar entre ambientes :-)
Guruprasad
Você pode dar uma olhada neste pacote: django-split-settings
sobolevn

Respostas:

86

Atualização: django-configurations foi lançado, o que é provavelmente uma opção melhor para a maioria das pessoas do que manualmente.

Se você preferir fazer as coisas manualmente, minha resposta anterior ainda se aplica:

Eu tenho vários arquivos de configurações.

  • settings_local.py - configuração específica do host, como nome do banco de dados, caminhos de arquivo, etc.
  • settings_development.py- configuração usada para desenvolvimento, por exemplo DEBUG = True.
  • settings_production.py- configuração usada para produção, por exemplo SERVER_EMAIL.

Eu amarro tudo isso junto com um settings.pyarquivo que primeiro importa settings_local.pye depois um dos outros dois. Ele decide qual carregar por duas configurações internas settings_local.py- DEVELOPMENT_HOSTSe PRODUCTION_HOSTS. settings.pychama platform.node()para encontrar o nome do host da máquina em que está sendo executado e, em seguida, procura por esse nome de host nas listas e carrega o segundo arquivo de configurações, dependendo da lista em que ele encontra o nome do host.

Dessa forma, a única coisa com que você realmente precisa se preocupar é manter o settings_local.pyarquivo atualizado com a configuração específica do host, e todo o resto é tratado automaticamente.

Veja um exemplo aqui .

Jim
fonte
2
e se a preparação (desenvolvimento) e a produção estiverem na mesma máquina? platform.node () retorna o mesmo então.
gwaramadze
2
O link de exemplo está desativado.
Jickson
Ótima ideia para determinar as configurações com base em listas de hosts! Meu único problema é a nomenclatura (settings_local.py é sempre importado primeiro, então quaisquer configurações que não sejam substituídas, ainda estarão ativas na produção, tornando o sufixo _localum tanto confuso) e o fato de que você não está usando módulos (configurações /base.py, settings / local.py, settings / production.py). Também seria sensato manter isso em um repositório separado ... melhor ainda, um serviço seguro que fornece essas informações de uma fonte canônica (provavelmente um exagero para a maioria) ... para que o novo host não exija um novo lançamento.
DylanYoung
Melhor ainda, se você estiver usando um software de gerenciamento de máquina, em vez de verificar a lista de hosts no .pyarquivo e, assim, dar a cada host acesso às informações sobre a configuração de todos os outros hosts, você pode modelar o manage.py para usar as configurações apropriadas arquivo em suas configurações de implantação.
DylanYoung
26

Pessoalmente, eu uso um único settings.py para o projeto, apenas peço que pesquise o nome do host em que está (minhas máquinas de desenvolvimento têm nomes de host que começam com "gabriel", então tenho apenas isto:

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

em outras partes, tenho coisas 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/'

e assim por diante. Um pouco menos legível, mas funciona bem e evita ter que manipular vários arquivos de configurações.

Gabriel Ross
fonte
Eu gosto dessa ideia, mas ela não me permite diferenciar entre diferentes instâncias do Django rodando no mesmo host. Isso aconteceria, por exemplo, se você tivesse diferentes instâncias em execução para diferentes subdomínios no mesmo host.
Erik
24

No final de settings.py, tenho o seguinte:

try:
    from settings_local import *
except ImportError:
    pass

Dessa forma, se eu quiser substituir as configurações padrão, preciso apenas colocar settings_local.py ao lado de settings.py.

Dmitry Shevchenko
fonte
4
Isso é um pouco perigoso porque, se um erro de digitação settings_localresultar em um ImportError, exceptele o engolirá silenciosamente.
Chris Martin
Você pode verificar a mensagem No module named...vs cannot import name..., mas é frágil. Ou coloque suas importações em settings_local.py em blocos try e gere uma exceção mais específica: MisconfiguredSettingsou algo nesse sentido.
DylanYoung
11

Eu tenho dois arquivos. settings_base.pyque contém configurações comuns / padrão e que são verificadas no controle de origem. Cada implantação possui um separado settings.py, que é executado from settings_base import *no início e, em seguida, substitui conforme necessário.

John Millikin
fonte
1
Eu uso isso também. É superior ao inverso ("from settings_local import *" de dmishe no final de settings.py) porque permite que as configurações locais acessem e modifiquem as globais, se necessário.
Carl Meyer
3
Se settings_local.pyfizer isso from settings import *, ele pode substituir os valores em settings.py. (o settings_local.pyarquivo deve ser importado no final settings.py).
Seth
Isso pode ser feito de qualquer maneira. Dê uma olhada em stackoverflow.com/a/7047633/3124256 acima. @Seth Essa é uma receita para uma importação circular.
DylanYoung
7

A maneira mais simplista que encontrei foi:

1) use o settings.py padrão para desenvolvimento local e 2) crie um production-settings.py começando com:

import os
from settings import *

Em seguida, basta substituir as configurações que diferem na produção:

DEBUG = False
TEMPLATE_DEBUG = DEBUG


DATABASES = {
    'default': {
           ....
    }
}
Andre Bossard
fonte
Como o Django sabe como carregar as configurações de produção?
AlxVallejo
2

Algo relacionado, para o problema de implantar o próprio Django com múltiplos bancos de dados, você pode querer dar uma olhada no Djangostack . Você pode baixar um instalador totalmente gratuito que permite instalar Apache, Python, Django, etc. Como parte do processo de instalação, permitimos que você selecione qual banco de dados deseja usar (MySQL, SQLite, PostgreSQL). Usamos os instaladores extensivamente ao automatizar implantações internamente (eles podem ser executados no modo autônomo).

Josué
fonte
1
Como alternativa, eu gostaria de recomendar Django Turnkey Linux baseado em uma pilha Ubuntu * NIX com django pré-instalado.
jochem
1

Tenho meu arquivo settings.py em um diretório externo. Dessa forma, ele não é verificado no controle de origem ou sobrescrito por uma implantação. Coloquei isso no arquivo settings.py em meu projeto Django, junto com todas as configurações padrão:

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

Observação: isso é muito perigoso se você não confiar em local_settings.py.

Chase Seibert
fonte
1

Além dos vários arquivos de configurações mencionados por Jim, também costumo colocar duas configurações em meu arquivo settings.py na parte superior BASE_DIRe BASE_URLdefinir como o caminho do código e a URL para a base do site, todas as outras configurações são modificadas para se anexar a estes.

BASE_DIR = "/home/sean/myapp/" por exemplo MEDIA_ROOT = "%smedia/" % BASEDIR

Portanto, ao mover o projeto, só preciso editar essas configurações e não pesquisar o arquivo inteiro.

Eu também recomendaria olhar o fabric e o Capistrano (ferramenta Ruby, mas pode ser usado para implantar aplicativos Django), que facilitam a automação da implantação remota.

Sean O Donnell
fonte
Ansible é python e oferece recursos de provisionamento muito mais robustos do que o Fabric. Eles combinam bem também.
DylanYoung
1

Bem, eu uso esta configuração:

No final de settings.py:

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

E em 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
fonte
1

Tantas respostas complicadas!

Cada arquivo settings.py vem com:

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

Eu uso esse diretório para definir a variável DEBUG assim (substitua com o diretório onde está seu código de desenvolvimento):

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

Então, toda vez que o arquivo settings.py for movido, DEBUG será False e será o seu ambiente de produção.

Sempre que você precisar de configurações diferentes das do seu ambiente de desenvolvimento, use:

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

Acho que depende do tamanho do site se você precisa intensificar o uso do SQLite. Usei o SQLite com sucesso em vários sites ativos menores e ele funciona muito bem.

Ycros
fonte
0

Eu uso o ambiente:

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

Eu acredito que esta é uma abordagem muito melhor, porque eventualmente você precisa de configurações especiais para seu ambiente de teste e você pode facilmente adicioná-las a essa condição.

slashmili
fonte
0

Este é um post mais antigo, mas acho que se adicionar este útil, libraryisso simplificará as coisas.

Use a configuração django

Começo rápido

pip install django-configurations

Em seguida, subclasse a classe configurations.Configuration incluída em settings.py do seu projeto ou qualquer outro módulo que você esteja usando para armazenar as constantes de configurações, por exemplo:

# mysite/settings.py

from configurations import Configuration

class Dev(Configuration):
    DEBUG = True

Defina a DJANGO_CONFIGURATIONvariável de ambiente com o nome da classe que você acabou de criar, por exemplo, em ~/.bashrc:

export DJANGO_CONFIGURATION=Dev

e a DJANGO_SETTINGS_MODULEvariável de ambiente para o caminho de importação do módulo como de costume, por exemplo, em bash:

export DJANGO_SETTINGS_MODULE=mysite.settings

Alternativamente, forneça a --configurationopção ao usar comandos de gerenciamento do Django ao longo das linhas da --settingsopção de linha de comando padrão do Django , por exemplo:

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

Para habilitar o Django a usar sua configuração, você agora tem que modificar seu script manage.py ou wsgi.py para usar as versões do django-configurations das funções iniciais apropriadas, por exemplo, um manage.py típico usando django-configurations ficaria assim:

#!/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 na linha 10 que não usamos a ferramenta comum, django.core.management.execute_from_command_linemas sim configurations.management.execute_from_command_line.

O mesmo se aplica ao seu arquivo wsgi.py , por exemplo:

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

Aqui não usamos a django.core.wsgi.get_wsgi_applicationfunção padrão , mas sim configurations.wsgi.get_wsgi_application.

É isso aí! Agora você pode usar seu projeto com manage.py e seu servidor habilitado para WSGI favorito.

Little Phild
fonte
-2

Na verdade, você provavelmente deve considerar ter as mesmas (ou quase as mesmas) configurações para seu ambiente de desenvolvimento e produção. Caso contrário, situações como "Ei, funciona na minha máquina" acontecerão de vez em quando.

Portanto, para automatizar sua implantação e eliminar esses problemas de WOMM, basta usar o Docker .

Dmitrii Mikhailov
fonte