我的用例是我需要将查询存储在数据库中并不时检索它们并进行评估。这是邮件应用程序所需要的,每个用户都可以订阅通过单独定制的查询选择的网站内容。
最基本的解决方案是存储原始 SQL 并将其与 RawQuerySet
一起使用。但我想知道是否有更好的解决方案?
最佳答案
乍一看,将查询构建工作交给其他人确实很危险,因为他们可以做任何事情(甚至删除数据库中的所有数据或删除整个表等)
即使您让他们构建查询的特定部分,它仍然对 Sql Injection 开放.如果所有这些危险都没有问题,那么您可以尝试以下操作。
这是我使用的旧脚本,让用户设置查询的特定部分。基础是使用 string.Template
和 eval
(邪恶的部分)
定义模型:
class SomeModel(Model):
usr = ForeingKey(User)
ct = ForeignKey(ContentType) # we will choose related DB table with this
extra_params = TextField() # store extra filtering criteria in here
让我们执行属于用户的所有查询。假设我们有一个 User
查询,其中包含 extra_params
is_staff
和 'username__iontains'
usr: somebody
ct: User
extra_params: is_staff=$stff_stat, username__icontains='$uname'
$
在extra_params 中定义占位符
from string import Template
for _qry in SomeModel.objects.filter(usr='somebody'): # filter somebody's queries
cts = Template(_qry.extra_params) # take extras with Template
f_cts = cts.substitute(stff_stat=True, uname='Lennon') # sustitute placeholders with real time filtering values
# f_cts is now `is_staff=True, username__icontains='Lennon'`
qry = Template('_qry.ct.model_class().objects.filter($f_cts)') # Now, use Template again to place our extras into a django `filter` query. We also select related model in here with `_qry.ct.model_class()`
exec_qry = qry.substitute(f_cts=f_cts)
# now we have `User.objects.filter(is_staff=True, username__icontains='Lennon')
query = eval(exec_qry) # lets evaluate it!
如果您已完成所有相关导入,那么您可以在 extra_params 中使用 Q
或任何其他查询构建选项。您也可以使用其他方法来形成Create
或Update
查询。
您可以阅读更多关于 Template
的信息在那里形成。但正如我所说。将此类选项提供给其他用户真的很危险。
您可能还需要阅读有关 Django Content Type 的内容
更新:如@GillBates 所述,您可以使用字典结构来创建查询。在这种情况下,您将不再需要 Template
。您可以使用 json 进行此类数据传输(如果您愿意,也可以使用任何其他格式)。假设您使用 json 从外部源获取数据,下面的代码是使用上层代码块中的一些变量的草稿。
input_data : '{"is_staff"=true, "username__icontains"="Lennon"}'
import json
_data = json.loads(input_data)
result_set = _qry.ct.model_class().objects.filter(**_data)
关于python - 如何序列化和反序列化 Django ORM 查询(不是查询集)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19560838/