Python Django从给定列表构建原始SQL查询

Python Django从给定列表构建原始SQL查询,python,sql,django,postgresql,Python,Sql,Django,Postgresql,我试图通过执行原始SQL查询从数据库后端获取一些信息。我需要将一个字段乘以一个因子,截断它,并以一种性能良好的方式将其转换为JSON。这就是我选择不在这里使用Django ORM的原因 with connection.cursor() as cursor: cursor.execute( ''' SELECT json_build_object( 'data', array_agg(r) ) FROM ( S

我试图通过执行原始SQL查询从数据库后端获取一些信息。我需要将一个字段乘以一个因子,截断它,并以一种性能良好的方式将其转换为JSON。这就是我选择不在这里使用Django ORM的原因

with connection.cursor() as cursor:
    cursor.execute(
      '''
      SELECT json_build_object(
        'data', array_agg(r)
      )
      FROM (
        SELECT
          time,
          trunc(column1 * 100, 2) as COL1,
          trunc(column2 * 100, 2) as COL2,
          [...]
        FROM measurements
          WHERE device_id=%s
          ORDER BY time DESC
          LIMIT 5
      ) r
      ''',
      [device_id]
  )
  result = cursor.fetchall()
我需要从以下列表中修改上述声明:

[
  {'column': 'column1', 'factor': 100, 'description': 'COL1', 'trunc': 2},
  {'column': 'column2', 'factor': 100, 'description': 'COL2', 'trunc': 2},
  [..]
]
因为我还不习惯python语法,所以我想知道是否有一个优雅的解决方案来创建这样一个语句。我知道我可以在dict列表上循环并附加查询,但我感觉不太好。如有任何建议,将不胜感激

我在想这样的事情:

['trunc({} * {}, {}) as {}'.format(
  d['column'], d['factor'], d['trunc'], d['description']) for d in l
]

如果您使用的是Psycopg2.7,那么您可以使用sql模块,这将确保一切安全

from psycopg2 import sql

query = sql.SQL('''
  SELECT json_build_object(
    'data', array_agg(r)
  )
  FROM (
    SELECT time, {}
    FROM measurements
      WHERE device_id=%s
      ORDER BY time DESC
      LIMIT 5
  ) r
''')

truncated_rows = sql.SQL(', ').join(
    sql.SQL('trunc({} * {}, {}) as {}').format(
        sql.Identifier(d['column']),
        sql.Literal(d['factor']),
        sql.Literal(d['trunc']),
        sql.Identifier(d['description'])
    )
    for d in l
)

with connection.cursor() as cursor:
    cursor.execute(query.format(truncated_rows), [device_id])
在2.6及更早版本中,您必须回到python字符串格式

','.join(
    'trunc({column} * {factor}, {trunc}) as {description}'.format(**data)
    for data in
    [
        {'column': 'column1', 'factor': 100, 'description': 'COL1', 'trunc': 2},
        {'column': 'column2', 'factor': 100, 'description': 'COL2', 'trunc': 2},
    ]
)