Szukałem odpowiedzi na to pytanie w witrynie South, Google i SO, ale nie mogłem znaleźć prostego sposobu, aby to zrobić.
Chcę zmienić nazwę modelu Django przy użyciu South. Załóżmy, że masz:
class Foo(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Foo)
i chcesz przekonwertować Foo na Bar, a mianowicie
class Bar(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Bar)
Aby to uprościć, po prostu próbuję zmienić nazwę z Foo
na Bar
, ale na razie zignoruję foo
członka FooTwo
.
Jaki jest najłatwiejszy sposób na zrobienie tego za pomocą South?
- Prawdopodobnie mógłbym przeprowadzić migrację danych, ale wydaje się to dość skomplikowane.
- Napisz niestandardową migrację, np.
db.rename_table('city_citystate', 'geo_citystate')
Ale nie jestem pewien, jak naprawić klucz obcy w tym przypadku. - Łatwiejszy sposób, który znasz?
python
django
django-models
rename
django-south
vaughnkoch
źródło
źródło
Odpowiedzi:
Odpowiadając na pierwsze pytanie, prosta zmiana nazwy modelu / tabeli jest dość prosta. Uruchom polecenie:
(Aktualizacja 2: spróbuj
--auto
zamiast--empty
uniknąć poniższego ostrzeżenia. Dzięki @KFB za wskazówkę).Jeśli używasz starszej wersji South, będziesz potrzebować
startmigration
zamiastschemamigration
.Następnie ręcznie edytuj plik migracji, aby wyglądał następująco:
Możesz to zrobić w prostszy sposób, używając
db_table
opcji Meta w swojej klasie modelu. Ale za każdym razem, gdy to robisz, zwiększasz wagę swojej bazy kodu - posiadanie nazw klas różniących się od nazw tabel sprawia, że kod jest trudniejszy do zrozumienia i utrzymania. W pełni popieram robienie prostych refaktoryzacji, takich jak ta ze względu na przejrzystość.(aktualizacja) Właśnie wypróbowałem to w środowisku produkcyjnym i otrzymałem dziwne ostrzeżenie, gdy poszedłem zastosować migrację. Powiedziało:
Odpowiedziałem „nie” i wszystko wydawało się być w porządku.
źródło
Wprowadź zmiany,
models.py
a następnie uruchomPo sprawdzeniu pliku migracji zobaczysz, że usuwa on tabelę i tworzy nową
Nie do końca tego chcesz. Zamiast tego edytuj migrację tak, aby wyglądała następująco:
W przypadku braku
update
oświadczeniadb.send_create_signal
wywołanie utworzy nowyContentType
z nową nazwą modelu. Ale lepiej jest po prostuupdate
to,ContentType
co już masz, na wypadek, gdyby wskazały na niego obiekty bazy danych (np. Poprzez aGenericForeignKey
).Ponadto, jeśli zmieniono nazwy niektórych kolumn, które są kluczami obcymi, na model o zmienionej nazwie, nie zapomnij o tym
źródło
contenttypes.ContentType
model do zamrożonych modeli za pomocą--frozen
flagi do./manage.py datamigration
. Na przykład:./manage.py datamigration --frozen contenttypes myapp update_contenttypes
. Następnie edytuj myapp_migrations / NNNN_update_contenttypes.py z kodem aktualizującym typ zawartości, jak określono powyżej.Południe nie może tego zrobić samo - skąd wie, że
Bar
reprezentuje to, coFoo
kiedyś? To jest rodzaj rzeczy, dla której napisałbym niestandardową migrację. Możesz zmienić swójForeignKey
kod tak, jak zrobiłeś to powyżej, a wtedy wystarczy zmienić nazwy odpowiednich pól i tabel, co możesz zrobić w dowolny sposób.Wreszcie, czy naprawdę musisz to zrobić? Nie muszę jeszcze zmieniać nazw modeli - nazwy modeli to tylko szczegół implementacji - szczególnie biorąc pod uwagę dostępność
verbose_name
opcji Meta.źródło
db_table
opcji Meta, aby zachować tę samą nazwę tabeli bazy danych.db_table
jest używany do wyprowadzania nazw kluczy obcych?Postępowałem zgodnie z powyższym rozwiązaniem Leopda. Ale to nie zmieniło nazw modeli. Zmieniłem to ręcznie w kodzie (również w powiązanych modelach, gdzie jest to określane jako FK). I przeprowadziłem kolejną migrację na południe, ale z opcją --fake. Dzięki temu nazwy modeli i nazwy tabel są takie same.
Właśnie sobie uświadomiłem, że można najpierw zacząć od zmiany nazw modeli, a następnie edytować plik migracji przed ich zastosowaniem. Dużo czystsze.
źródło