Django:RunSQL:使用PostgreSQL COPY命令

13

我尝试使用以下RunSQL命令运行迁移:

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

它会出现以下这种失败情况:

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
< p >在< code >RunSQL中是否不允许使用< code >COPY?< /p > < p >我们使用psycopg2< /p >

1
这肯定不是标准输入,是吧?为什么不使用 INSERT 语句呢? - Daniel Roseman
@DanielRoseman 它可以使用 psql -f myfile.sql 运行。对于新手来说,这两种用法看起来非常相似。 - guettli
1个回答

7
psycopg2驱动程序提供了copy_tocopy_from方法,可用于实现与psql客户端相同的行为;关键是使用RunPython操作而不是RunSQL操作。

您需要:

  • 在迁移中编写一个函数,打开文件并与复制方法进行交互
  • 在迁移的operations列表中使用RunPython操作调用该函数

例如,使用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)
    ]

一些注意事项:

  • 传递给 copyfile 对象本质上是语句中的 STDIN
  • 复制命令可能对列有所挑剔;使用 copy_expert,您可以控制与命令相同的所有选项:格式、标题、分隔符等。

有关 copy_* 方法的更多信息,请查看 psycopg2 文档:http://initd.org/psycopg/docs/cursor.html


谢谢。方法copy_from()解决了一个语句的复制问题。不幸的是,我的转储文件中有几个复制语句。但我可以将其分成N个部分。 - guettli
1
啊,我没有想到这一点。我想你有几个不同的选择 - 1)剪切文件(小心解析SQL语句),2)重新审查数据生成方式,或者3)通过process.popen生成psql命令。#3取决于命令将在何处运行,可能会更加脆弱。对于#2,您可以使用copy_to方法直接转换为.csv格式,省略每个转储中的SQL语句。 - bimsapi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接