Eu estava procurando uma resposta para isso no site da South, Google e SO, mas não consegui encontrar uma maneira simples de fazer isso.
Eu quero renomear um modelo Django usando South. Digamos que você tenha o seguinte:
class Foo(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Foo)
e você deseja converter Foo para Bar, a saber
class Bar(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Bar)
Para simplificar, estou apenas tentando alterar o nome de Foo
para Bar
, mas ignore o foo
membro FooTwo
por enquanto.
Qual é a maneira mais fácil de fazer isso usando o Sul?
- Provavelmente eu poderia fazer uma migração de dados, mas isso parece bastante envolvido.
- Escreva uma migração personalizada, por exemplo
db.rename_table('city_citystate', 'geo_citystate')
, mas não tenho certeza de como corrigir a chave estrangeira neste caso. - Uma maneira mais fácil que você conhece?
python
django
django-models
rename
django-south
vaughnkoch
fonte
fonte
Respostas:
Para responder à sua primeira pergunta, a simples renomeação de modelo / tabela é bastante direta. Execute o comando:
(Atualização 2: tente em
--auto
vez de--empty
evitar o aviso abaixo. Agradecemos a @KFB pela dica.)Se você estiver usando uma versão mais antiga do sul, precisará em
startmigration
vez deschemamigration
.Em seguida, edite manualmente o arquivo de migração para ficar assim:
Você pode fazer isso mais simplesmente usando a
db_table
opção Meta na sua classe de modelo. Mas sempre que você faz isso, aumenta o peso herdado da sua base de código - ter nomes de classes diferentes dos nomes de tabelas torna seu código mais difícil de entender e manter. Apoio totalmente a refatoração simples como essa por uma questão de clareza.(atualização) Eu apenas tentei isso em produção e recebi um aviso estranho quando fui aplicar a migração. Dizia:
Eu respondi "não" e tudo parecia estar bem.
fonte
Faça as alterações
models.py
e executeAo inspecionar o arquivo de migração, você verá que ele exclui uma tabela e cria uma nova
Isto não é exatamente o que você deseja. Em vez disso, edite a migração para que se pareça com:
Na ausência da
update
instrução, adb.send_create_signal
chamada criará um novoContentType
com o novo nome do modelo. Mas é melhor apenasupdate
o queContentType
você já possui, caso haja objetos de banco de dados apontando para ele (por exemplo, via aGenericForeignKey
).Além disso, se você renomeou algumas colunas que são chaves estrangeiras para o modelo renomeado, não se esqueça de
fonte
contenttypes.ContentType
modelo aos modelos congelados usando o--frozen
sinalizador para./manage.py datamigration
. Por exemplo:./manage.py datamigration --frozen contenttypes myapp update_contenttypes
. Em seguida, edite myapp_migrations / NNNN_update_contenttypes.py com o código de atualização do tipo de conteúdo, conforme especificado acima.O Sul não pode fazer isso sozinho - como ele sabe que
Bar
representa o queFoo
costumava fazer? É para esse tipo de coisa que eu escreveria uma migração personalizada. Você pode alterar o seuForeignKey
código como você fez acima e, em seguida, é apenas um caso de renomear os campos e tabelas apropriados, que você pode fazer da maneira que desejar.Finalmente, você realmente precisa fazer isso? Eu ainda preciso renomear modelos - os nomes dos modelos são apenas um detalhe da implementação - particularmente dada a disponibilidade da
verbose_name
opção Meta.fonte
db_table
opção Meta para manter o mesmo nome da tabela do banco de dados.db_table
é usado para derivar nomes de chaves estrangeiras?Eu segui a solução de Leopd acima. Mas isso não mudou os nomes dos modelos. Eu mudei manualmente no código (também em modelos relacionados, onde isso é chamado de FK). E fez outra migração para o sul, mas com a opção --fake. Isso faz com que os nomes dos modelos e da tabela sejam os mesmos.
Acabado de perceber, é possível primeiro começar com a alteração dos nomes dos modelos e editar o arquivo de migrações antes de aplicá-los. Muito mais limpo.
fonte