Eu tenho um aplicativo django com quatro modelos. Percebo agora que um desses modelos deve estar em um aplicativo separado. Eu tenho o sul instalado para migrações, mas não acho que isso possa ser feito automaticamente. Como posso migrar um dos modelos do aplicativo antigo para um novo?
Além disso, lembre-se de que vou precisar que este seja um processo repetitivo, para que eu possa migrar o sistema de produção e tal.
django
migration
django-south
Apreche
fonte
fonte
Respostas:
Como migrar usando o sul.
Digamos que temos dois aplicativos: comuns e específicos:
Agora, queremos mover o modelo common.models.cat para um aplicativo específico (precisamente para specific.models.cat). Primeiro faça as alterações no código fonte e depois execute:
Agora precisamos editar os dois arquivos de migração:
Agora, as duas migrações de aplicativos estão cientes da mudança e a vida é um pouco menos :-) Definir esse relacionamento entre migrações é a chave do sucesso. Agora, se você fizer:
fará a migração e
migrará as coisas para baixo.
Observe que, para a atualização do esquema, usei o aplicativo comum e, para o downgrade, usei o aplicativo específico. Isso ocorre porque a dependência aqui funciona.
fonte
orm['contenttypes.contenttype'].objects.filter
linha na parte de trás0003_create_cat
também? Também quero compartilhar uma dica. Se você tiver índices, eles também precisarão ser modificados. No meu caso eram índices únicos, então meus Aguarda assim:db.delete_unique('common_cat', ['col1'])
db.rename_table('common_cat', 'specific_cat')
db.delete_unique('specific_cat', ['col1'])
orm['contenttypes.contenttype']
, você também precisa adicionar a--freeze contenttypes
opção aos seusschemamigration
comandos.python manage.py schemamigration specific create_cat --auto --freeze common
para acessar o modelo de gato no aplicativo comum.Para construir sobre potr Czachur 's resposta , situações que envolvem ForeignKeys são mais complicado e deve ser tratado de forma ligeiramente diferente.
(O exemplo a seguir se baseia nos aplicativos
common
especific
mencionados na resposta atual).mudaria para
Corrida
geraria as seguintes migrações (estou intencionalmente ignorando as alterações do Django ContentType - consulte a resposta mencionada anteriormente para saber como lidar com isso):
Como você pode ver, o FK deve ser alterado para fazer referência à nova tabela. Precisamos adicionar uma dependência para que saibamos a ordem em que as migrações serão aplicadas (e, assim, que a tabela existirá antes de tentarmos adicionar um FK a ela), mas também precisamos garantir que a rolagem para trás funcione também porque o dependência se aplica na direção inversa .
De acordo com a documentação do Sul ,
depends_on
garantirá que seja0004_auto__add_cat
executado antes0009_auto__del_cat
ao migrar para a frente, mas na ordem oposta ao migrar para trás . Se deixássemosdb.rename_table('specific_cat', 'common_cat')
naspecific
reversão, acommon
reversão falharia ao tentar migrar a ForeignKey porque a tabela mencionada na tabela não existiria.Espero que isso esteja mais próximo de uma situação do "mundo real" do que as soluções existentes e alguém ache isso útil. Felicidades!
fonte
Os modelos não são muito acoplados aos aplicativos, portanto, a movimentação é bastante simples. O Django usa o nome do aplicativo no nome da tabela do banco de dados, portanto, se você deseja mover o aplicativo, pode renomear a tabela do banco de dados por meio de uma
ALTER TABLE
instrução SQL ou, ainda mais simples, basta usar odb_table
parâmetro naMeta
classe do seu modelo para consultar a Antigo nome.Se você já usou ContentTypes ou relações genéricas em qualquer lugar do seu código até agora, provavelmente desejará renomear o
app_label
do contenttype apontando para o modelo que está sendo movido, para que as relações existentes sejam preservadas.Obviamente, se você não tem nenhum dado a preservar, a coisa mais fácil a fazer é eliminar completamente as tabelas do banco de dados e executar
./manage.py syncdb
novamente.fonte
Aqui está mais uma correção para a excelente solução da Potr. Adicione o seguinte a specific / 0003_create_cat
A menos que essa dependência seja definida, o Sul não garantirá que a
common_cat
tabela exista no momento em que específico / 0003_create_cat for executado, lançando umdjango.db.utils.OperationalError: no such table: common_cat
erro em você.O sul executa migrações em ordem lexicográfica, a menos que a dependência seja explicitamente definida. Como
common
vem antes despecific
todas ascommon
migrações serem executadas antes da renomeação da tabela, provavelmente não seria reproduzido no exemplo original mostrado pelo Potr. Mas se você renomearcommon
paraapp2
especific
paraapp1
você, encontrará esse problema.fonte
O processo em que eu decidi desde que voltei aqui algumas vezes e decidi formalizá-lo.
Esta foi originalmente construída sobre a resposta de potr Czachur e resposta de Matt Briançon , usando 0.8.4 do Sul
Etapa 1. Descubra relacionamentos de chave estrangeira filho
Portanto, neste caso estendido, descobrimos outro modelo relacionado como:
Etapa 2. Crie migrações
Etapa 3. Controle de origem: confirme as alterações até o momento.
Torna o processo mais repetitivo se você tiver conflitos de mesclagem, como colegas de equipe que escrevem migrações nos aplicativos atualizados.
Etapa 4. Adicione dependências entre as migrações.
Basicamente,
create_kittycat
depende do estado atual de tudo, e tudo dependecreate_kittycat
.Etapa 5. A tabela renomeia a alteração que queremos fazer.
Etapa 6. Somente se você precisar que o backwards () funcione E faça com que o KeyError seja executado ao contrário.
Etapa 7. Teste - o que funciona para mim pode não ser suficiente para a sua situação na vida real :)
fonte
Portanto, usar a resposta original do @Potr acima não funcionou para mim no Sul 0.8.1 e no Django 1.5.1. Estou publicando o que funcionou para mim abaixo, na esperança de que seja útil para outras pessoas.
fonte
Vou dar uma versão mais explícita de uma das coisas que Daniel Roseman sugeriu em sua resposta ...
Se você acabou de alterar o
db_table
atributo Meta do modelo, você mudou para apontar para o nome da tabela existente (em vez do novo nome que o Django daria se você soltasse e fizesse umsyncdb
), então você pode evitar migrações sul complicadas. por exemplo:Original:
Depois de se mudar:
Agora você só precisa fazer uma migração de dados para atualizar o
app_label
paraMyModel
nadjango_content_type
tabela e deve estar pronto ...Execute
./manage.py datamigration django update_content_type
e edite o arquivo que South cria para você:fonte