Para um projeto no Django, tenho que usar dois bancos de dados: padrão e remoto . Eu criei routers.py
e tudo funciona bem.
Havia um requisito para criar uma tabela no banco de dados remoto e eu criei a migração, execute-a e a tabela django_migrations
foi criada. Eu quero ter apenas uma tabela django_migrations
, no banco de dados padrão.
A parte relevante routers.py
é aqui:
class MyRouter(object):
# ...
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'my_app':
return db == 'remote'
return None
Eu executo a migração assim:
python manage.py migrate my_app --database=remote
Agora quando eu faço:
python manage.py runserver
Recebo o seguinte aviso:
Você tem 1 migração (s) não aplicada (s). Seu projeto pode não funcionar corretamente até você aplicar as migrações para o (s) aplicativo (s): my_app.
Execute 'python manage.py migrate' para aplicá-los.
As tabelas para my_app
são criadas no remote
banco de dados e, django_migrations
dentro do remote
banco de dados, as migrações são marcadas como aplicadas.
EDIT:
Como forçar o Django a usar apenas uma tabela django_migrations
, mas ainda aplicar as migrações em diferentes bancos de dados?
Como aplicar as migrações em diferentes bancos de dados para que nenhum aviso seja gerado?
fonte
django_migrations
tabela compartilhada , será necessário diferenciar entre linhas com migrações paradefault
eremote
db. Isso é bem profundo nos internos do django. Eu correria o risco de afirmar que isso exigiria grande reescrita do código de migração.Respostas:
Graças aos comentários sobre minha pergunta, fiz algumas pesquisas e descobri as seguintes conclusões.
O uso de vários bancos de dados resulta na criação de uma tabela
django_migrations
quando as migrações são usadas. Não há opção para registrar as migrações em apenas uma tabeladjango_migrations
, como explica o comentário de Kamil Niski . Isso fica claro após a leitura do arquivodjango/db/migrations/recorder.py
.Ilustrarei um exemplo com um projeto
foo
e um aplicativobar
dentro do projeto. O aplicativobar
possui apenas um modeloBaz
.Criamos o projeto:
Agora, temos este conteúdo dentro do diretório principal do projeto:
Eu tenho o hábito de agrupar todos os aplicativos dentro do diretório do projeto:
No arquivo
foo/settings.py
, ajustamos as configurações para usar dois bancos de dados diferentes. Para os fins deste exemplo, usamossqlite3
:Agora, executamos as migrações:
Isso executa todas as migrações, a parte
--database=default
é opcional, porque se não for especificado, o Django usa o banco de dados padrão.O Django aplicou todas as migrações ao banco de dados padrão:
Agora criamos o modelo
Baz
:models.py
:registre o aplicativo
bar
emINSTALLED_APPS
(foo/settings.py
) e crie as migrações:Antes de executar as migrações que criamos
routers.py
dentro dobar
aplicativo:e registre-o em
foo/settings.py
:Agora, a abordagem ingênua seria executar as migrações para
bar
oremote
banco de dados:As migrações foram aplicadas ao
remote
banco de dados:Quando corremos:
o seguinte aviso será gerado:
Tudo parece funcionar bem embora. No entanto, não é satisfatório receber esse aviso.
A maneira correta seria executar todas as migrações para cada banco de dados, conforme sugerido nesta resposta .
Seria assim:
e depois de criar as migrações para
bar
:O roteador cuidará para que a tabela
bar_baz
seja criada apenas noremote
banco de dados, mas o Django marcará as migrações como aplicadas nos dois bancos de dados. Também as mesas paraauth
,admin
,sessions
, etc. será criado apenas nodefault
banco de dados, conforme especificado norouters.py
. A tabeladjango_migrations
noremote
banco de dados também terá registros para essas migrações.É uma leitura longa, mas espero que ajude a esclarecer isso, na minha opinião, questão não completamente explicada na documentação oficial .
fonte