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?

  1. I could pewnie przeprowadzi migrację danych, ale wydaje się to dość skomplikowane.
  2. napisz niestandardową migrację, np. db.rename_table('city_citystate', 'geo_citystate'), ale nie jestem pewien, jak naprawić klucz obcy w tym przypadku.
  3. łatwiejszy sposób, który znasz?
Author: Serjik, 2010-05-19

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ł:

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'.
Odpowiedziałam " nie " i wszystko wydawało się w porządku.
 128
Author: Leopd,
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)
 66
Author: Jian,
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.

Wreszcie, czy naprawdę musisz to robić? Muszę jeszcze zmienić nazwy modeli - nazwy modeli są tylko szczegółem implementacji - szczególnie biorąc pod uwagę dostępność verbose_name opcja Meta.
 5
Author: Dominic Rodger,
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.

 -1
Author: gowthaman,
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