2015-09-03 11 views

Antwort

0

Diese Information wird in der Migrationsklasse nicht bereitgestellt. Sie wird im schema_editor-Attribut bereitgestellt, das an eine RunPython-Operation übergeben wird. Einige Beispiele für die Verwendung dieses Beispiels finden Sie unter the documentation.

4

Ich hatte gerade das gleiche Bedürfnis. Ich musste eine Migration bearbeiten, die den Anfangswert einer Sequenz festlegte, die auf postgres aber nicht sqlite funktioniert. Hier ist, wie ich die RunSQL in einem RunPython verpackt habe, indem ich der Dokumentation folgte, mit der Daniel verlinkt ist.

from django.db import migrations 


def forwards(apps, schema_editor): 
    if not schema_editor.connection.vendor == 'postgres': 
     return 
    migrations.RunSQL(
     "alter sequence api_consumer_id_seq restart with 1000500;") 


class Migration(migrations.Migration): 
    dependencies = [ 
     ('api', '0043_auto_20160416_2313'), 
    ] 

    operations = [ 
     migrations.RunPython(forwards), 
    ] 
+1

Mein Herstellerzeichen war 'postgresql' und nicht' postgres' (in Django 1.10.6) –

+0

Das Problem dabei ist, dass 'migrations.RunSQL()' ein Objekt zurückgibt. Es führt tatsächlich kein SQL aus, bis die Methode '_run_sql()' des Objekts mit bestimmten Parametern aufgerufen wird. Siehe die Antwort von PaulMest für eine Lösung, die ebenfalls die Methode 'migrations.RunPython()' verwendet, SQL jedoch so ausführt, dass SQL tatsächlich ausgeführt wird. – radicalbiscuit

3

Ich löste ein ähnliches Problem heute - um eine Migration durchzuführen, ein neues Modell zu schaffen, sondern nur für eine Postgres DB - und ich diese Frage gefunden. Aber die Antwort von Matthew hat mir nicht geholfen. Tatsächlich bin ich mir nicht sicher, ob es überhaupt funktioniert. Das liegt daran, dass die Zeile mit migrations.RunSQL(...) nicht tatsächlich ausführen SQL; es erstellt ein neues Objekt des Typs RunSQL, die eine Command ist, und dann sofort verworfen.

Hier ist, wie ich das Problem lösen endete, falls jemand für „django bedingte Migration“ in der Zukunft zu suchen versucht:

from __future__ import unicode_literals 

import django.contrib.postgres.fields 
from django.db import migrations, models 


class PostgresOnlyCreateModel(migrations.CreateModel): 
    def database_forwards(self, app_label, schema_editor, from_state, to_state): 
     if schema_editor.connection.vendor.startswith("postgres"): 
      super(PostgresOnlyCreateModel, self).database_forwards(app_label, schema_editor, from_state, to_state) 

    def database_backwards(self, app_label, schema_editor, from_state, to_state): 
     if schema_editor.connection.vendor.startswith("postgres"): 
      super(PostgresOnlyCreateModel, self).database_backwards(app_label, schema_editor, from_state, to_state) 


class Migration(migrations.Migration): 

    dependencies = [ 
     ...whatever... 
    ] 

    operations = [ 
     PostgresOnlyCreateModel(
      name='...whatever...', 
      fields=[...whatever...], 
     ), 
    ] 
4

Hier ist, wie ich das Problem gelöst, da ich nicht RunSQL bekommen könnte innen arbeiten RunPython. Zum Glück hat das schema_editor Objekt eine execute() method.

def forwards(apps, schema_editor): 
    if not schema_editor.connection.vendor.startswith('postgres'): 
     logger.info('Database vendor: {}'.format(schema_editor.connection.vendor)) 
     logger.info('Skipping migration without attempting to ADD CONSTRAINT') 
     return 

    schema_editor.execute('ALTER TABLE my_table ADD CONSTRAINT my_constraint (my_field != \'NaN\';)') 


def backwards(apps, schema_editor): 
    if not schema_editor.connection.vendor.startswith('postgres'): 
     logger.info('Database vendor: {}'.format(schema_editor.connection.vendor)) 
     logger.info('Skipping migration without attempting to DROP CONSTRAINT') 
     return 

    schema_editor.execute('ALTER TABLE my_table DROP CONSTRAINT my_constraint;') 


class Migration(migrations.Migration): 

    dependencies = [ 
     ... 
    ] 

    operations = [ 
     migrations.RunPython(forwards, backwards, atomic=True) 
    ] 
+0

Dies funktionierte für mich, außer dass ich Atom = – kzh

+0

haben sollte Seien Sie vorsichtig mit "atomic = False". Wenn einige Aktionen erfolgreich sind und andere fehlschlagen, kann Ihre Datenbank in einem inkonsistenten Zustand enden. – PaulMest

+0

Django würde sich weigern, es für mich anders zu führen. – kzh