Manter o código de execução durante syncdb
-
06-09-2019 - |
Pergunta
Eu tenho algum código que lança causas syncdb para lançar um erro (porque ele tenta acessar o modelo antes das tabelas são criadas).
Existe uma maneira de manter o código seja executado em syncdb? algo como:
if not syncdb:
run_some_code()
Obrigado:)
Editar : PS - Pensei em usar o sinal post_init ... para o código que acessa o banco de dados, é que uma boa idéia
Mais informações
Aqui está mais algumas informações, conforme solicitado:)
Eu executar para esse algumas vezes, por exemplo ... Eu estava cortando em django-cron e determinou que é necessário para fazer trabalhos de certeza que não são existentes quando você carrega Django (porque ele procura todos os aplicativos instalados para empregos e adiciona-los na carga de qualquer maneira).
Então eu adicionei o seguinte código no início do arquivo __init__.py
:
import sqlite3
try:
# Delete all the old jobs from the database so they don't interfere with this instance of django
oldJobs = models.Job.objects.all()
for oldJob in oldJobs:
oldJob.delete()
except sqlite3.OperationalError:
# When you do syncdb for the first time, the table isn't
# there yet and throws a nasty error... until now
pass
Por razões óbvias esta é uma porcaria. ele está vinculado ao sqlite e estou há melhores lugares para colocar este código (isto é apenas como me deparei com a questão), mas ele funciona.
Como você pode ver o erro que você recebe é erro operacional (em SQLite) e o rastreamento de pilha diz algo ao longo das linhas de "django_cron_job tabela não encontrado"
Solução
No final, o objetivo era executar algum código antes de quaisquer páginas foram carregadas .
Isso pode ser feito através da execução-lo no arquivo urls.py, uma vez que tem de ser importados antes de uma página pode ser servido (obviamente).
E eu era capaz de remover essa tentativa feio / except deus bloco :) Obrigado (e S. Lott)
Solução
"edit:? PS - Pensei em usar o sinal post_init ... para o código que acessa o banco de dados, é que uma boa idéia"
Nunca.
Se você tem o código que está acessando o modelo antes das tabelas são criadas, você tem grandes, grandes problemas. Você provavelmente está fazendo algo seriamente errado.
Normalmente, você corre SyncDB aproximadamente uma vez. O banco de dados é criado. E sua aplicação web usa o banco de dados.
Às vezes, você fez uma alteração design, eliminar e recriar o banco de dados. E então seus usos de aplicações web que banco de dados por um longo tempo.
Você (geralmente) não precisa de código em um módulo __init__.py
. Você deve (quase) nunca tem código executável que faz o trabalho real em um módulo __init__.py
. É muito, muito raro, e impróprio para Django.
Eu não sei por que você está mexendo com __init__.py
quando Django Cron diz que você fazer o seu regime de agendamento em urls.py
.
Editar
registros de compensação é uma coisa.
Brincando com __init__.py
e base.py
do Django-cron são claramente completamente errado maneiras de fazer isso. Se é assim tão complicado, você está fazendo errado.
É impossível dizer o que você está tentando fazer, mas deve ser trivial.
Seu urls.py
só pode ser executado após syncdb e depois de todo o material ORM foi configurado e ligado corretamente.
Seu urls.py
poderia, por exemplo, excluir algumas linhas e, em seguida, adicionar algumas linhas a uma tabela. Neste ponto, todas as questões SyncDB estão fora do caminho.
Por que você não tem a sua lógica em urls.py
?
Outras dicas
O código que tenta acessar a modelos antes de serem criadas pode muito bem existir apenas no nível do módulo; ele teria que ser executado código executável quando o módulo é importado, como o seu exemplo indica. Isto é, como você adivinhou, o motivo pelo syncdb falhar. Tenta para importar o módulo, mas o acto de importação do módulo faz com código de nível de aplicação para executar; um "efeito colateral" se você quiser.
O desejo de importações módulo evitar que causam efeitos colaterais é tão forte em Python que a convenção if __name__ == '__main__':
para scripts Python executáveis ??tem se tornado comum. Quando apenas carregar uma biblioteca de código faz com que uma aplicação para iniciar a execução, dores de cabeça se seguem: -)
Para aplicativos Django, isso se torna mais do que uma dor de cabeça. Considere o efeito de ter oldJob.delete()
executada toda vez que o módulo é importado. Pode parecer que ele está executando apenas uma vez quando você executa com o servidor de desenvolvimento do Django, mas em um ambiente de produção que serão executados com bastante frequência. Se você usar Apache, por exemplo, o Apache irá freqüentemente fogo até vários processos filhos esperando para pedidos punho. Como uma longa execução avanços servidor, seu aplicativo Django vai ficar bootstrapped cada vez que um manipulador é bifurcada para o seu servidor web, o que significa que o módulo será importado e delete()
será chamado várias vezes, muitas vezes de forma imprevisível. Um sinal não vai ajudar, infelizmente, como o sinal poderia ser acionado toda vez que um processo Apache é inicializado também.
Não é, aliás, apenas um servidor que poderia causar seu código para executar inadvertidamente. Se você usar ferramentas como epydoc, por exemplo, eles irá importar o código para gerar documentação de API. Este, por sua vez causaria a lógica do aplicativo para iniciar a execução, o que é, obviamente, um efeito colateral indesejado de apenas correr um analisador documentação.
Por este motivo, o código de limpeza como este é ou melhor tratado por um trabalho cron, que procura empregos obsoletos em uma base periódica e limpa o DB. Este script personalizado também pode ser executado manualmente ou por qualquer processo (por exemplo, durante a implantação, ou como parte de sua função de teste setUp()
unidade para garantir um teste limpo). Não importa como você fazê-lo, o ponto importante é que um código como este deve ser sempre executada explicitamente , em vez de implicitamente como resultado de abrir o arquivo de origem.
Espero que ajude. Eu sei que não fornece uma maneira de determinar se syncdb está funcionando, mas a questão syncdb magicamente irá desaparecer se você projetar seu aplicativo Django com implantação de produção em mente.