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

时间:2013-10-24 08:30:07

标签: python sql django serialization

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

3 个答案:

答案 0 :(得分:3)

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

即使您让他们构建查询的特定部分,它仍然可以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

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

  

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或任何其他查询构建选项。您还可以使用其他方法来形成CreateUpdate个查询。

您可以在此处详细了解Template表单。但正如我所说。 非常危险 可以向其他用户提供此类选项。

此外,您可能需要阅读Django Content Type

更新:正如@GillBates所提到的,您可以使用dictonary结构来创建查询。在这种情况下,您将不再需要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)

答案 1 :(得分:2)

根据你的回答,

  

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

一个选项是存储参数(pickle'd或json'ed,或在模型中)并使用常规django方法重建查询。这是一个更强大的解决方案,因为它可以处理一些数据结构更改。

答案 2 :(得分:1)

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