2016-07-11 23 views
4

Ich habe ein Django-Modell, das einen Fremdschlüssel auf ein anderes Modell hat:Django 1.9 Drop Fremdschlüssel in der Migration

class Example(models.Model) 
    something = models.ForeignKey(SomeModel, db_index=True) 

ich die zugrunde liegende DB-Säule als ein Feld halten will, aber die ausländischen loszuwerden Schlüsseleinschränkung in der Datenbank.

Also das Modell ändern:

class Example(models.Model): 
    something_id = models.IntegerField() 

Und klar zu sein, something_id ist die Spalte, die Django für das Fremdschlüsselfeld geschaffen hatte.

Ich möchte die Spalte nicht löschen und neu erstellen (das ist es, was Django macht, wenn ich Migrationen automatisch erzeuge, nachdem ich das Modell wie oben geändert habe).

Ich möchte das Feld aber behalten Ich möchte die Fremdschlüsseleinschränkung in der Datenbank mit einer Migration entfernen. Es ist mir nicht klar, wie man das mit einer Django-Migration macht - gibt es eine eingebaute Unterstützung dafür oder muss ich etwas Roh-SQL ausführen und, wenn ja, wie bekomme ich programmatisch den Namen der Beschränkung?

Antwort

5

Dies ist, wie ich es geschafft, es basiert auf nimasmi Antwort oben:

class Migration(migrations.Migration): 
    dependencies = [ 
     ('my_app', '0001_initial'), 
    ] 

    # These *WILL* impact the database! 
    database_operations = [ 
     migrations.AlterField(
      model_name='Example', 
      name='something', 
      field=models.ForeignKey('Something', db_constraint=False, db_index=True, null=False) 
     ), 
    ] 

    # These *WON'T* impact the database, they update Django state *ONLY*! 
    state_operations = [ 
     migrations.AlterField(
      model_name='Example', 
      name='something', 
      field=models.IntegerField(db_index=True, null=False) 
     ), 
     migrations.RenameField(
      model_name='Example', 
      old_name='something', 
      new_name='something_id' 
     ), 
    ] 

    operations = [ 
     migrations.SeparateDatabaseAndState(
      database_operations=database_operations, 
      state_operations=state_operations 
     ) 
    ] 
+0

Ich habe das auch ausprobiert und gearbeitet. Das Problem ist, wenn ich danach eine neue Migration durchführen muss, wird die Statusänderung nicht erkannt und funktioniert nur basierend auf dem Datenbankschema. Hast du das auch gekreuzt? –

5

Siehe SeparateDatabaseAndState. Es ermöglicht Ihnen, einen Django (Status) Teil der Migration getrennt von der Datenbank Teil der Migration anzugeben.

  1. Das Feld in Ihrer Modelldatei ändern.
  2. Erstellen Sie die Migration wie gewohnt.

    class Migration(migrations.Migration): 
    
        dependencies = [ 
         ('my_app', '0001_whatever.py'), 
        ] 
    
        operations = [ 
         migrations.AlterField(
          model_name='example', 
          name='something', 
          field=models.CharField(max_length=255, null=True)), 
         ), 
        ] 
    
  3. Jetzt ändern dies manuell: Sie werden mit etwas wie Ende

    class Migration(migrations.Migration): 
    
        dependencies = [ 
         ('my_app', '0001_whatever.py'), 
        ] 
    
        state_operations = [ 
         migrations.AlterField(
          model_name='example', 
          name='something', 
          field=models.CharField(max_length=255, null=True)), 
         ), 
        ] 
        operations = [ 
         migrations.SeparateDatabaseAndState(state_operations=state_operations) 
        ] 
    

Beachten Sie, dass Sie keine database_operations Argument angeben, so dass die Django Beziehungen geändert werden, aber Die Datenbankdaten sind unverändert.

Unnötig zu sagen: Machen Sie eine Sicherungskopie, bevor Sie dies versuchen.

+0

Vielen Dank für Ihre Antwort, aber das ist nicht ganz das, was ich will; Ich möchte die Fremdschlüsseleinschränkung der Datenbank entfernen (dh ich möchte eine Migration, die so etwas wie "ALTER TABLE-Beispiele DROP CONSTRAINT x" macht) –

+0

Sie möchten, dass Django denkt, dass es noch ein Fremdschlüssel ist, aber die Datenbank zu glauben, dass es ein einfaches Textfeld ist ? – nimasmi

+0

Entschuldigung, ich habe diesen Teil vermisst: Ich möchte die zugrunde liegende DB-Spalte (something_id) behalten, das Modell wird aktualisiert, um 'something_id' als Integer-Feld zu haben, aber ich möchte die Datenbank-Fremdschlüssel-Einschränkung fallen lassen. Ich werde die Frage aktualisieren –