繁体   English   中英

如何序列化和反序列化Django ORM查询(不是queryset)?

[英]How to serialize and deserialize Django ORM query (not queryset)?

我的用例是我需要将查询存储在数据库中,并不时检索它们并进行评估。 那是mailing-app所需要的,每个用户都可以订阅由单独定制的查询选择的网站内容。 最基本的解决方案是存储原始SQL并将其与RawQuerySet一起RawQuerySet 但是我想知道是否有更好的解决方案?

乍一看,将查询构建工作交给其他人确实很危险,因为他们可以做任何事情(甚至删除数据库中的所有数据或删除整个表等)。

即使您让他们构建查询的特定部分,它也对Sql Injection开放。 如果所有这些危险都可以,那么您可以尝试以下方法。

这是我使用的旧脚本,允许用户设置查询的特定部分。 基础知识使用string.Templateeval (最糟糕的部分)

定义模型:

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

让我们执行所有属于用户的查询。 假设我们有一个带有extra_params is_staff和'username__iontains'的User查询

usr:有人

ct:用户

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内容类型的信息

更新:如@GillBates所述,您可以使用字典结构来创建查询。 在这种情况下,您将不再需要Template 您可以使用json进行此类数据传输(如果需要,也可以使用其他方式)。 假设您使用json从外部源获取数据,则以下代码是从头开始的,该步骤使用了上层代码块中的某些变量。

input_data:'{“ is_staff” = true,“ username__icontains” =“列侬”}'

import json
_data = json.loads(input_data)
result_set = _qry.ct.model_class().objects.filter(**_data)

根据您的回答,

用户将一些特定于内容的参数传递到表单中,然后查看接收POST的函数,构造查询

一种选择是存储参数(点刺式或json式,或在模型中),并使用常规django手段重建查询。 由于它可以处理某些数据结构更改,因此它在某种程度上更可靠。

您可以创建一个新的模型user_option并将选择存储在此表中。 根据您的问题,很难确定它是否是更好的解决方案,但这会使用户的选择在数据结构中更加明确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM