2010-04-14 48 views
2

这是我的第一个问题接受作为参数的文本字符串时,奇怪的行为。的Django +南+的Python:使用功能

我试图执行在Django一个SQL查询(向南迁移):

from django.db import connection 
# ... 
class Migration(SchemaMigration): 
    # ... 
    def transform_id_to_pk(self, table): 
     try: 
      db.delete_primary_key(table) 
     except: 
      pass 
     finally: 
      cursor = connection.cursor() 

      # This does not work 
      cursor.execute('SELECT MAX("id") FROM "%s"', [table]) 

      # I don't know if this works. 
      try: 
       minvalue = cursor.fetchone()[0] 
      except: 
       minvalue = 1 
      seq_name = table + '_id_seq' 

      db.execute('CREATE SEQUENCE "%s" START WITH %s OWNED BY "%s"."id"', [seq_name, minvalue, table]) 
      db.execute('ALTER TABLE "%s" ALTER COLUMN id SET DEFAULT nextval("%s")', [table, seq_name + '::regclass']) 
      db.create_primary_key(table, ['id']) 
    # ... 

我用这个函数是这样的:

self.transform_id_to_pk('my_table_name') 

所以应该:

  1. 找到的最大的存在ID或0(崩溃)
  2. 创建序列南Ë
  3. 创建序列
  4. 更新的ID字段使用序列
  5. 更新ID作为PK

但它崩溃和错误说:

File "../apps/accounting/migrations/0003_setup_tables.py", line 45, in forwards 
    self.delegation_table_setup(orm) 
    File "../apps/accounting/migrations/0003_setup_tables.py", line 478, in delegation_table_setup 
    self.transform_id_to_pk('accounting_delegation') 
    File "../apps/accounting/migrations/0003_setup_tables.py", line 20, in transform_id_to_pk 
    cursor.execute(u'SELECT MAX("id") FROM "%s"', [table.encode('utf-8')]) 
    File "/Library/Python/2.6/site-packages/django/db/backends/util.py", line 19, in execute 
    return self.cursor.execute(sql, params) 
psycopg2.ProgrammingError: relation "E'accounting_delegation'" does not exist 
LINE 1: SELECT MAX("id") FROM "E'accounting_delegation'" 
          ^

我已经缩短了文件路径以方便使用。

是什么 “E'accounting_delegation'” 是什么意思?我怎么能摆脱它?

谢谢!

卡洛斯。

+0

我不得不说我是新来的python,django,南... – carlosescri 2010-04-14 11:18:26

回答

4

的问题是,你正在使用DB-API参数的事情是不是SQL数据。当你做这样的事情:

cursor.execute('INSERT INTO table_foo VALUES (%s, %s)', (col1, col2)) 

的DB-API模块(Django的为你使用任何数据库,在这种情况下,前端)会知道适当地逃脱“COL1”和“COL2”的内容,并取代%s与他们在一起。请注意,%s的周围没有引号。但是,这仅适用于SQL 数据,而不是SQL ,如表名和序列的名字,因为他们需要(或者根本没有。)当你做

cursor.execute('INSERT INTO "%s" VALUES (%s, %s)', (tablename, col1, col2)) 

在以不同的方式引用表名被引述,如果你的意思是它是字符串数据插入,和你结束了,例如“‘table_foo’”。您需要将SQL元数据,这是查询的一部分,你的SQL数据,这是不是,分开就像这样:

sql = 'INSERT INTO TABLE "%s" VALUES (%%s, %%s)' % (tablename,) 
cursor.execute(sql, (col1, col2)) 

注意,因为Django的DB-API前端的paramstyle是“pyformat”(它使用%s作为占位符),当您执行字符串格式化来创建要执行的SQL时,您需要将其转义。并且请注意,当您从不安全的源获取表名并且不验证它时,这对于SQL注入攻击是不安全的。

+0

谢谢你的教训,我学到了很多东西。 – carlosescri 2010-04-14 11:58:38