Najprostszy sposób na zmianę nazwy modelu za pomocą Django / South?
Szukałam odpowiedzi na to na stronie South, Google, i tak, ale nie mogłam znaleźć prostego sposobu, aby to zrobić.
Chcę zmienić nazwę modelu Django używając South. Powiedz, że masz następujące:
class Foo(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Foo)
I chcesz przekonwertować Foo Na Bar, czyli
class Bar(models.Model):
name = models.CharField()
class FooTwo(models.Model):
name = models.CharField()
foo = models.ForeignKey(Bar)
Żeby było prościej, staram się zmienić nazwę z Foo
na Bar
, ale na razie ignoruję foo
członka w FooTwo
.
Jak najłatwiej to zrobić używając południa?
- I could pewnie 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?
4 answers
Aby odpowiedzieć na pierwsze pytanie, prosta zmiana nazwy modelu / tabeli jest dość prosta. Uruchom polecenie:
./manage.py schemamigration yourapp rename_foo_to_bar --empty
(Aktualizacja 2: Spróbuj --auto
zamiast --empty
, Aby uniknąć ostrzeżenia poniżej. Dzięki @KFB za wskazówkę.)
Jeśli używasz starszej wersji south, Potrzebujesz startmigration
zamiast schemamigration
.
Następnie ręcznie Edytuj plik migracji, aby wyglądał tak:
class Migration(SchemaMigration):
def forwards(self, orm):
db.rename_table('yourapp_foo', 'yourapp_bar')
def backwards(self, orm):
db.rename_table('yourapp_bar','yourapp_foo')
Możesz to osiągnąć w prosty sposób, korzystając z opcji Meta db_table
w klasie modelu. Ale każdy czas, w którym to zrobisz, zwiększysz wagę swojej bazy kodowej - posiadanie nazw klas różniących się od nazw tabel sprawia, że kod jest trudniejszy do zrozumienia i utrzymania. W pełni popieram takie proste refaktoryzacje dla jasności.
(update) właśnie próbowałem tego w produkcji i dostałem dziwne ostrzeżenie, gdy poszedłem zastosować migrację. Powiedział:
Odpowiedziałam " nie " i wszystko wydawało się w porządku.The following content types are stale and need to be deleted: yourapp | foo Any objects related to these content types by a foreign key will also be deleted. Are you sure you want to delete these content types? If you're unsure, answer 'no'.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-09 20:49:08
Wprowadź zmiany w models.py
, a następnie uruchom
./manage.py schemamigration --auto myapp
Po sprawdzeniu pliku migracji zobaczysz, że usuwa on tabelę i tworzy nową
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting model 'Foo'
db.delete_table('myapp_foo')
# Adding model 'Bar'
db.create_table('myapp_bar', (
...
))
db.send_create_signal('myapp', ['Bar'])
def backwards(self, orm):
...
Nie do końca tego chcesz. Zamiast tego edytuj migrację tak, aby wyglądała następująco:
class Migration(SchemaMigration):
def forwards(self, orm):
# Renaming model from 'Foo' to 'Bar'
db.rename_table('myapp_foo', 'myapp_bar')
if not db.dry_run:
orm['contenttypes.contenttype'].objects.filter(
app_label='myapp', model='foo').update(model='bar')
def backwards(self, orm):
# Renaming model from 'Bar' to 'Foo'
db.rename_table('myapp_bar', 'myapp_foo')
if not db.dry_run:
orm['contenttypes.contenttype'].objects.filter(app_label='myapp', model='bar').update(model='foo')
W przypadku braku instrukcji update
, wywołanie db.send_create_signal
utworzy nowy ContentType
o nowej nazwie modelu. Ale lepiej po prostu update
ContentType
już masz w przypadku, gdy są obiekty bazodanowe wskazujące na to (np. via a GenericForeignKey
).
Również, jeśli zmieniłeś nazwę kolumn, które są kluczami obcymi na przemianowany model, nie zapomnij
db.rename_column(myapp_model, foo_id, bar_id)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 04:07:05
Południe nie może tego zrobić sam - skąd wie, że Bar
reprezentuje to, co Foo
kiedyś? To jest coś, dla czego napisałbym niestandardową migrację. Możesz zmienić ForeignKey
w kodzie, tak jak to zrobiłeś powyżej, a potem jest to tylko przypadek zmiany nazw odpowiednich pól i tabel, co możesz zrobić w dowolny sposób.
verbose_name
opcja Meta.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-19 05:25:08
Zastosowałem się do powyższego rozwiązania. Ale to nie zmieniło nazw modeli. Zmieniłem go ręcznie w kodzie(również w pokrewnych modelach, gdzie jest to określane jako FK). I zrobił kolejną migrację na południe, ale z ... fałszywą opcją. Powoduje to, że nazwy modeli i tabel są takie same.
Właśnie sobie uświadomiłem, że można zacząć od zmiany nazw modeli, a następnie edytować plik migracji przed ich zastosowaniem. Dużo czystsze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 21:38:02