2012-02-22 156 views
3

我试图使一个模型的自定义原始查询和我得到这个错误:问题Django的原始查询参数

DatabaseError: error de sintaxis en o cerca de «E'positions_statusrecord'» LINE 1: SELECT id FROM E'positions_statusrecord' WHERE "type"=E'Leav...

这里是原始查询我想要使用(这是一个管理方法):

def get_status_ids(self, model): 
    """ 
    This query returns the latest statuses ids for each entry 
    of "model" in StatusRecord. 
    """ 
    db_table = self.model._meta.db_table 
    model_type = model.get_status_type() 

    raw_query = (
     "SELECT id " 
     "FROM %s " 
     "WHERE \"type\"=%s AND " 
     "(identifier,date_time) IN " 
       "(" 
          "SELECT identifier, Max(date_time) " 
          "FROM %s " 
          "WHERE \"type\"=%s " 
          "GROUP BY identifier" 
       ")" 
    ) 

    params = (db_table, model_type, db_table, model_type,) 
    return self.raw(raw_query, params) 

我试图用一个简单的查询(只是一个SELECT ... FROM ..),并有同样的问题。似乎原始查询不能使用参数完成FROM部分。

我是对的吗?还是我犯了一个错误,我没有找到它?

我使用的是PostgreSQL 8.4.10,django 1.3和python 2.6。

我搜索了有关原始查询参数的信息,看看是否有一些禁止格式化选项,但我没有找到任何帮助我的东西。

有谁知道是什么原因导致了这个错误?

回答

2

It seems to be that raw queries couldn't have the "FROM" part completed with a parameter.

是的,ORM会引用字符串参数使其成为... FROM 'some_table' ...

由于db_table参数是可信的(不是源自用户输入),你可以这样做:

raw_query = (
    "SELECT id " 
    "FROM %s " 
    "WHERE \"type\"=%%s AND " 
    "(identifier,date_time) IN " 
      "(" 
         "SELECT identifier, Max(date_time) " 
         "FROM %s " 
         "WHERE \"type\"=%%s " 
         "GROUP BY identifier" 
      ")" 
) % (db_table, db_table) 
return self.raw(raw_query, (model_type, model_type)) 

由于Django Aggregation can be used in filters,也许你可以得到相同的结果,而不是诉诸原始SQL(看起来也是in lookup example)。

看看您是否可以用QuerySet.extra()替换raw(),并用EXISTS替换SQL IN

+0

感谢您的快速回答!我认为总是建议将参数传递给“params”参数中的原始查询。我是安全问题的新手,所以我一直试图以这种方式使用它。但在这种情况下,这是值得信赖的投入。 关于“EXISTS”问题,我想我以前做过,但换个方式说,我有一些性能问题。如果我是对的,那个查询会为表中的每个条目创建一个子查询,并且该表中有很多条目(超过2000个)。虽然我认为我已经做到了,但我会再试一次。非常感谢你! – marianobianchi 2012-02-23 03:11:53

+0

@marianobianchi:2000条目相当小,你可能看不到'IN'和'EXISTS'之间的区别。 – 2012-02-23 13:08:22