Estou escrevendo uma classe do Django Middleware que quero executar apenas uma vez na inicialização, para inicializar algum outro código arbritário. Eu segui a solução muito boa postada por sdolan aqui , mas a mensagem "Hello" é enviada ao terminal duas vezes . Por exemplo
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
print "Hello world"
raise MiddlewareNotUsed('Startup complete')
e no meu arquivo de configurações do Django, tenho a classe incluída na MIDDLEWARE_CLASSES
lista.
Mas quando executo o Django usando o runserver e solicito uma página, entro no terminal
Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET / HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0
Alguma idéia de por que "Hello world" é impresso duas vezes? Obrigado.
Respostas:
Atualização da resposta do Pykler abaixo: O Django 1.7 agora tem um gancho para isso
Não faça assim.
Você não quer "middleware" para iniciar uma única vez.
Você deseja executar o código no nível superior
urls.py
. Esse módulo é importado e executado uma vez.urls.py
fonte
Atualização: O Django 1.7 agora tem um gancho para isso
Arquivo:
myapp/apps.py
Arquivo:
myapp/__init__.py
Para Django <1.7
A resposta número um parece não funcionar mais, urls.py é carregado na primeira solicitação.
O que funcionou ultimamente é colocar o código de inicialização em qualquer um dos arquivos init .py do seu INSTALLED_APPS.
myapp/__init__.py
Ao usar
./manage.py runserver
... isso é executado duas vezes, mas isso ocorre porque o servidor de execução tem alguns truques para validar os modelos primeiro etc ... implantações normais ou mesmo quando o servidor de recarga é recarregado automaticamente, isso é executado apenas uma vez.fonte
Esta pergunta é bem respondida na publicação do blog Gancho de ponto de entrada para projetos Django , que funcionará para Django> = 1.4.
Basicamente, você pode
<project>/wsgi.py
fazer isso, e ele será executado apenas uma vez, quando o servidor iniciar, mas não quando você executar comandos ou importar um módulo específico.fonte
Se isso ajudar alguém, além da resposta do pykler, a opção "--noreload" evita que o runserver execute o comando na inicialização duas vezes:
Mas esse comando não recarregará o runserver após as alterações de outros códigos.
fonte
os.environ.get('RUN_MAIN')
apenas executar o seu código uma vez no processo principal (ver stackoverflow.com/a/28504072 )ready(self)
chamadas enquanto ainda era possível iniciá-las apenas uma vez. Felicidades!runserver
por padrão inicia dois processos com números pid distintos (diferentes).--noreload
faz com que inicie um processo.Como sugerido por @Pykler, no Django 1.7+ você deve usar o gancho explicado em sua resposta, mas se quiser que sua função seja chamada apenas quando o servidor de execução for chamado (e não ao fazer migrações, migrações, shell etc.), é chamado ) e você deseja evitar as exceções AppRegistryNotReady , da seguinte maneira:
Arquivo:
myapp/apps.py
fonte
Observe que você não pode conectar-se com confiabilidade ao banco de dados ou interagir com modelos dentro da
AppConfig.ready
função (consulte o aviso nos documentos).Se você precisar interagir com o banco de dados no código de inicialização, uma possibilidade é usar o
connection_created
sinal para executar o código de inicialização após a conexão com o banco de dados.Obviamente, esta solução é para executar código uma vez por conexão com o banco de dados, não uma vez por início do projeto. Portanto, você desejará um valor razoável para a
CONN_MAX_AGE
configuração, para não executar novamente o código de inicialização em todas as solicitações. Observe também que o servidor de desenvolvimento ignoraCONN_MAX_AGE
, portanto você executará o código uma vez por solicitação em desenvolvimento.Em 99% das vezes, isso é uma má idéia - o código de inicialização do banco de dados deve ser usado nas migrações - mas há alguns casos de uso em que você não pode evitar a inicialização tardia e as advertências acima são aceitáveis.
fonte
my_receiver
função de desconectar-se doconnection_created
sinal, especificamente, adicione o seguinte para amy_receiver
função:connection_created.disconnect(my_receiver)
.se você quiser imprimir "olá mundo" uma vez quando executar o servidor, coloque print ("olá mundo") fora da classe StartupMiddleware
fonte