我有一个不寻常的场景,但除了我的sql
参数之外,我还需要让用户/ API定义表列名。我对params
的问题是查询导致:
SELECT device_id, time, 's0' ...
而不是
SELECT device_id, time, s0 ...
是否有另一种方法可以通过raw
执行此操作,还是我需要自己退出该列?
queryset = Measurement.objects.raw(
'''
SELECT device_id, time, %(sensor)s FROM measurements
WHERE device_id=%(device_id)s AND time >= to_timestamp(%(start)s) AND time <= to_timestamp(%(end)s)
ORDER BY time ASC;
''', {'device_id': device_id, 'sensor': sensor, 'start': start, 'end': end})
答案 0 :(得分:1)
与SQL注入的任何可能性一样,小心。
但基本上这是一个相当普遍的问题,有一个相当安全的解决方案。一般来说,问题是查询参数是处理查询值的“正确方法”,但它们不是为模式元素设计的。
要在查询中动态包含架构元素,通常必须求助于字符串连接。我们都被告知不要使用SQL查询。
但这里的好消息是你不必使用实际的用户输入。这是因为,尽管可能的查询值是无限的,但可能的有效模式元素的超集是非常有限的。因此,您可以针对该超集验证用户的输入。
例如,请考虑以下过程:
所以你所使用的只是你作为程序员放入代码的字符串。这与自己编写SQL无关。
答案 1 :(得分:0)
对于您发布的示例查询,您似乎不需要raw()
。我认为以下查询集非常相似。
measurements = Measurement.objects.filter(
device_id=device_id,
to_timestamp__gte=start,
to_timestamp__lte,
).order_by('time')
for measurement in measurements:
print(getattr(measurement, sensor)
如果您需要优化并避免加载其他字段,可以使用values()
或only()
。