2011-09-20 13 views
6

segue è il mio modello:Rinominare una classe-nome del modello Django e corrispondenti chiavi esterne con il Sud, senza perdere i dati

class myUser_Group(models.Model): 
    name = models.CharField(max_length=100) 


class Channel(models.Model): 
    name = models.CharField(max_length=100) 
    description = models.CharField(max_length=1000) 
    belongs_to_group = models.ManyToManyField(myUser_Group) 

class Video(models.Model): 
    video_url = models.URLField(max_length=300) 
    belongs_to_channel = models.ManyToManyField(Channel) 
    description = models.CharField(max_length=1000) 
    tags = TagField() 

class UserProfile(models.Model): 
     user = models.OneToOneField(User) 

class User_History(models.Model): 
    date_time = models.DateTimeField() 
    user = models.ForeignKey(UserProfile, null=True, blank=True) 
    videos_watched = models.ManyToManyField(Video) 

Volevo solo per rimuovere le sottolineature dai tutti i nomi di classe in modo che User_History sembra UserHistory, anche le chiavi esterne devono essere aggiornate. Ho provato a usare il sud ma non sono riuscito a trovarlo nel documentario.

Un modo è esportare i dati, disinstallare il sud, eliminare la migrazione, rinominare la tabella e quindi importare nuovamente i dati. c'è un altro modo per farlo?

+0

e si desidera questo fatto in amministrazione? in tal caso http://stackoverflow.com/questions/7413488/where-do-i-customize-the-heading-for-the-modeladmin-view/7414247#7414247 dovrebbe aiutare – Pannu

+0

Sì, molto vero! ma ho ancora bisogno di cambiare i nomi dei modle, per aderenza a pep-8. – whatf

risposta

8

È possibile farlo utilizzando solo sud.

Per questo esempio ho un app chiamato usergroups con il seguente modello:

class myUser_Group(models.Model): 
    name = models.CharField(max_length=100) 

che presumo è già sotto il controllo della migrazione con il Sud.

Fai il cambio di nome del modello:

class MyUserGroup(models.Model): 
    name = models.CharField(max_length=100) 

e creare una migrazione vuoto da sud

$ python manage.py schemamigration usergroups model_name_change --empty 

Questo creerà un file di migrazione scheletro per di specificare cosa succede. Se modifichiamo esso in modo che assomiglia a questo (questo file sarà nel app_name/migrazioni/cartella - Gruppi/migrazioni/in questo caso):

import datetime 
from south.db import db 
from south.v2 import SchemaMigration 
from django.db import models 

class Migration(SchemaMigration): 

    def forwards(self, orm): 
     # Change the table name from the old model name to the new model name 
     # ADD THIS LINE (using the correct table names) 
     db.rename_table('usergroups_myuser_group', 'usergroups_myusergroup') 


    def backwards(self, orm): 
     # Provide a way to do the migration backwards by renaming the other way 
     # ADD THIS LINE (using the correct table names) 
     db.rename_table('usergroups_myusergroup', 'usergroups_myuser_group') 


    models = { 
     'usergroups.myusergroup': { 
      'Meta': {'object_name': 'MyUserGroup'}, 
      'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 
      'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 
     } 
    } 

    complete_apps = ['usergroups'] 

Nel metodo forwards stiamo rinominando il nome di tabella di database per abbinare ciò che l'ORM django cercherà con il nome del nuovo modello. Invertire la modifica in backwards per garantire che la migrazione possa essere ripristinata se necessario.

Eseguire la migrazione senza la necessità di importare/esportare i dati exisiting:

$ python manage.py migrare

L'unico passo rimanente è quello di aggiornare la chiave esterna e molti-a-molti in colonne i modelli che fanno riferimento a myUser_Group e cambiano per fare riferimento a MyUserGroup.

1

La soluzione di mmcnickle può funzionare e sembra ragionevole ma preferisco un processo in due fasi. Nel primo passaggio cambi il nome della tabella.

nel modello assicuratevi di avere il vostro nuovo nome della tabella in:

class Meta: 
     db_table = new_table_name' 

Poi, come mmcnickle suggerito, creare una migrazione personalizzata:

python manage.py schemamigration xyz migration_name --empty 

Si può leggere di più su questo qui: https://docs.djangoproject.com/en/dev/ref/models/options/

Ora con la tua migrazione personalizzata aggiungi anche la linea per rinominare il tuo tavolo avanti e indietro:

Questo può essere sufficiente per migrare e modificare il nome della tabella, ma se si è utilizzato il nome della tabella personalizzata Classe Meta prima di allora sarà necessario fare un po 'di più. Quindi direi di norma, per sicurezza, effettuare una ricerca nel file di migrazione per "old_table_name" e modificare le voci che si trovano nel nuovo nome della tabella. Ad esempio, se in precedenza si utilizzava il nome della tabella Classe Meta personalizzato, è probabile vedere:

'Meta': {'object_name': 'ModelNameYouWillChangeNext', 'db_table': "u'old_table_name'"}, 

quindi avrai bisogno di cambiare il vecchio nome della tabella a quello nuovo.

Ora è possibile eseguire la migrazione con:

python manage.py migrate xyz 

A questo punto la vostra applicazione dovrebbe funzionare dal momento che tutto quello che hai fatto è cambiare il nome della tabella e dire Django a cercare il nuovo nome della tabella.

Il secondo passaggio consiste nel modificare il nome del modello. La difficoltà dipende molto dalla tua app, ma in pratica devi solo modificare tutto il codice che fa riferimento al nome del vecchio modello per il codice che fa riferimento al nome del nuovo modello. Probabilmente hai anche bisogno di cambiare alcuni nomi di file e nomi di directory se hai usato il vecchio nome del modello in loro per scopi organizzativi.

Dopo aver eseguito questa operazione, l'app dovrebbe funzionare correttamente. A questo punto il tuo compito è praticamente completato e la tua app dovrebbe funzionare correttamente con un nuovo nome di modello e un nuovo nome di tabella. L'unico problema con cui utilizzerai South è la prossima volta che crei una migrazione utilizzando la sua funzione di rilevamento automatico, tenterà di eliminare la vecchia tabella e crearne una nuova da zero perché ha rilevato il tuo nuovo nome di modello. Per risolvere questo problema è necessario creare un'altra migrazione personalizzata:

python manage.py schemamigration xyz tell_south_we_changed_the_model_name_for_old_model_name --empty 

La cosa bella è qui non fate niente dal momento che avete già cambiato il nome del modello in modo da Sud raccoglie questo. Basta migrare con "pass" nella migrazione avanti e indietro:

python manage.py migrate xyz 

Nulla è stato fatto e del Sud ora si rende conto che sia aggiornato. Prova:

python manage.py schemamigration xyz --auto 

e si dovrebbe vedere rileva nulla è cambiato