2015-08-07 12 views
8

ich versuche, eine Wanderung mit dem folgenden RunSQL Befehl auszuführen:Django: RunSQL: verwenden PosgreSQL COPY-Befehl

class Migration(migrations.Migration): 
    operations = [ 
     RunSQL(
r''' 
COPY auth_group (id, name) FROM stdin; 
1 TEST-GROUP 
\. 
''')] 

es so nicht:

File "/home/foo/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 63, in execute 
    return self.cursor.execute(sql) 
django.db.utils.ProgrammingError: syntax error at or near "1" 
LINE 3: 1 TEST-GROUP 

Gibt es COPY nicht in RunSQL erlaubt?

Wir verwenden psycopg2

+1

Sicherlich ist dies nicht STDIN , ist es? Warum verwenden Sie keine INSERT-Anweisung? –

+0

@DanielRoseman funktioniert es mit 'psql -f myfile.sql'. Beide Anwendungen sehen einem Neuling sehr ähnlich. – guettli

Antwort

2

Der psycopg2 Treiber copy_to und copy_from Verfahren aussetzt, die verwendet werden können, das gleiche Verhalten wie der psql Client zu implementieren; Der Schlüssel ist, die RunPython Operation anstelle der RunSQL Operation zu verwenden.

Sie benötigen:

  • Eine Funktion in der Migration Ihre Datei zu öffnen und die Interaktion mit den Kopiermethoden
  • A RunPython Betrieb in Ihrem Migrations operations Liste die Funktion
aufzurufen

Beispiel mit Django 1.8.4, Python 2.7.10, psycopg2 2.6.1 -

from django.db import models, migrations 

def forwards(apps, schema_editor): 
    with open('./path/to/file.csv', 'r') as infile: 
     with schema_editor.connection.cursor() as stmt: 
      #for finer control, use copy_expert instead 
      stmt.copy_from(infile, 'your_table', sep=',') 

class Migration(migrations.Migration): 

    dependencies = [ 
    ] 

    operations = [ 
     #this runs your function 
     migrations.RunPython(forwards) 
    ] 

Einige Anmerkungen:

  • Das file Objekt copy geben wird, ist im Wesentlichen STDIN in der Erklärung.
  • Der Kopierbefehl kann bei Spalten wählerisch sein; mit copy_expert Sie alle die gleichen Optionen wie der Befehl steuern: Format, Header-Trennzeichen usw.

Für weitere Informationen über die copy_* Methoden, überprüfen Sie die psycopg2 docs: http://initd.org/psycopg/docs/cursor.html

+0

Danke. Die Methode 'copy_from()' löst die 'copy' für eine Anweisung. Leider gibt es in meiner Dump-Datei mehrere copy-Anweisungen. Aber ich kann es in N Stücke schneiden. – guettli

+1

Ah, ich habe diese Verbindung nicht hergestellt. Ich nehme an, Sie haben ein paar verschiedene Optionen - 1) schneiden Sie die Datei (vorsichtig, um die SQL-Anweisung zu analysieren), 2) zu überprüfen, wie die Daten generiert werden, oder 3) spawn den Befehl psql über 'process.popen'. # 3 ist etwas fragiler, abhängig davon, wo der Befehl ausgeführt wird. Für # 2 können Sie direkt zu .csv gehen, indem Sie die Methode 'copy_to' für die Daten verwenden, an denen Sie interessiert sind, und die SQL-Anweisung in jedem Speicherauszug weglassen. – bimsapi