Django Postgres生成错误的脚本psycopg2 - 引用表名

时间:2013-03-28 14:43:16

标签: django postgresql psycopg2

Django 1.5
PostgreSQL 9.2
psycopg2 2.4.6

我正在使用QuerySet API的额外功能,以便能够使用来自Postgres的多维数据集扩展的函数 - 我知道额外的由于可移植性原因不是很好,但我不打算另外使用其他数据库(不是之后) Postgres,不!)。所以问题是我从这段代码得到了错误的SQL查询:

return self.select_related('item_place').extra(
            select={ 'distance': 'round(earth_distance(ll_to_earth(%s, %s), ll_to_earth(%s.latitude, %s.longitude))::numeric, 0)' },
            select_params=[latitude, longitude, ItemPlace._meta.db_table, ItemPlace._meta.db_table],
            where=['round(earth_distance(ll_to_earth(%s, %s), ll_to_earth(%s.latitude, %s.longitude))::numeric, 0) <= %s'],
            params=[latitude, longitude, ItemPlace._meta.db_table, ItemPlace._meta.db_table, radius])

似乎psycopg2用单引号包围表名,这对于Postgres是不正确的,在执行的脚本中我可以看到:

round(earth_distance(ll_to_earth(%s, %s), ll_to_earth('item_place'.latitude, 'item_place'.longitude))::numeric, 0)

我应该使用表名,因为我在另一个表中有纬度和经度而没有它我会得到“ambigous column”错误。现在我不知道,也许我做错了,这就是为什么我得到这个错误,或者这可能是psycopg2中的一个错误?有什么想法吗?

1 个答案:

答案 0 :(得分:2)

根据the docparamsselect_params用于表示Psycopg2引用参数。它不是用于引用表名(通过双引号完成)。

引用the doc of Psycopg2

  

只应通过此方法绑定变量值:它不应该   用于设置表或字段名称。对于这些元素,普通的字符串   在运行execute()之前应该使用格式化。

此外,我们通常不会使用需要双引号的标识符作为表名ref the comment of this answer。因此,可以直接在代码中使用表名:

return self.select_related('item_place').extra(
        select={ 'distance': 'round(earth_distance(ll_to_earth(%s, %s), ll_to_earth({tbl}.latitude, {tbl}.longitude))::numeric, 0)'.format(tbl=ItemPlace._meta.db_table) },
        select_params=[latitude, longitude],
        where=['round(earth_distance(ll_to_earth(%s, %s), ll_to_earth({tbl}.latitude, {tbl}.longitude))::numeric, 0) <= %s'.format(tbl=ItemPlace._meta.db_table)],
        params=[latitude, longitude])