django - 如何在 Django 中动态创建多级分层表单?
问题描述
我正在使用 Django 为科学数据库构建高级搜索页面。目标是能够允许一些动态创建的复杂搜索,使用and
&加入搜索词组or
。
通过遵循这个例子,我走到了那里,它允许多个术语一起使用。它基本上是一组动态创建的搜索词,我可以将它们组合在一起或组合在一起。例如
<field1|field2> <is|is not|contains|doesn't contain> <search term> <->
<+>
... where<->
将删除搜索词行并<+>
添加新行。
但我希望用户能够添加另一个搜索词行,或者添加一个和组和一个或组,这样我就有了类似的东西:
<and-group|or-group> <->
<field1|field2> <is|is not|contains|doesn't contain> <search term> <->
<+term|+and-group|_or-group>
然后用户可以添加术语或组。结果搜索可能最终如下:
and-group
compound
is
lysine
or-group
tissue
is
brain
tissue
is
spleen
feeding status
is not
fasted
因此,生成的过滤器将如下所示。
Data.objects.filter(Q(compound="lysine") & (Q(tissue=brain) | Q(tissue="spleen")) & ~Q(feeding_status="fasted"))
注意 - 我不一定要问如何让下面的过滤器表达式正确 - 它只是我试图弄清楚的动态分层构造组件。 如果我的Q
和/或filter
语法错误,请原谅。我以前做过这些查询,但我对 Django 还是陌生的,所以在这里把它从我的脑海中浮现出来几乎可以保证是零机会。我也跳过了我在这里跨越的模型关系,所以为了简单起见,我们假设这些都是同一个模型中的所有字段。
我不确定如何将括号动态添加到过滤器表达式,但我当前的代码可以轻松地将单个Q
表达式与and
or连接起来or
。
我也不确定如何动态创建层次结构来创建子组。我猜任何这样的解决方案都必须是一个黑客,并且没有建立机制来做这样的事情......
这是我目前正在工作的屏幕截图示例:
更新:
我发现这个例子真的很远。在将它合并到我的 Django 项目中之前,我分叉了那个小提琴并得到了这个概念证明:
http://jsfiddle.net/hepcat72/d42k38j1/18/
控制台准确地吐出我想要的对象。并且没有错误。单击搜索按钮可用于表单验证。我留空的任何字段都会提示填写该字段。这是一个演示 gif:
现在我需要处理 POST 输入以构造查询(我认为我可以处理)并恢复结果上方的表单 - 我不太确定如何完成 - 也许是自定义标签中的递归函数?
虽然,有没有办法对表单进行快照并在结果加载到它下方时恢复它?或者可能将结果加载到不同的框架中?
解决方案
我不知道我是不是在教奶奶吸鸡蛋,但万一不是,Python语言的一个特性可能会很有用。
foo( bar = 27, baz = None)
可以改为编码
args = {}
a1, a2 = 'bar', 'baz'
d[a1] = 27
d[a2] = None
foo( **args )
因此可以构造由运行时键和值指定的任意 Q 对象q1 = Q(**args)
IIRCq1 & q2
并且q1 | q2
它们本身就是 Q 对象,因此您可以构建任意复杂度的过滤器。
我还将提及Django-filter,这通常是我对过滤此类问题的回答,但我怀疑在这种情况下,您所追求的权力比它容易提供的权力更大。基本上,它会将用户指定的过滤条件列表“和”在一起。内置的很简单 .filter( key=value)
,但是通过添加代码,您可以使用与用户提供的值相关的复杂 Q 表达式创建自定义过滤器。
至于表单,Django 表单是线性构造,而表单集是相似表单的列表。我想我可能会求助于 JavaScript 在浏览器中构建某种表示复杂查询的树,并让提交按钮将其编码为 JSON 并通过单个文本字段返回它(或者request.POST
不使用表单就将其挑选出来) . 可能已经编写了一些 Javascript 来执行此操作,但我不知道。您需要确保恶意提交的字段名称和值不会导致安全问题。对于纯粹的过滤操作,这基本上相当于确保用户在任何情况下都有权获取数据库表中的所有数据。
Django PostgreSQL 扩展中有一个 JSONField表单,它验证用户提供的(或 Javascript 生成的)文本确实是 JSON,并将其作为 Python 字典和列表提供给您。
推荐阅读
- angular - 如何在 ng build --prod 之后运行 index.html 文件
- r - 这两个命令行有什么区别?
- python - 如何使用 nltk 计算文本中存在的单词的频率
- docker - 由于 exit cmd 挂起,无法从容器中退出
- sql - 具有多个频率的 Oracle 调度程序作业
- python - 亚马逊使用 bs4 阻止 Python 3 抓取,请求
- c# - 将 ac# 字符串保存为 html 文件
- vue.js - 如何在 Nuxt、Vue 中实现 Facebook Messenger 客户聊天 SDK?
- excel - 我们如何保护 excel 工作表,但工作扩展行
- android - YouTube 数据 API 返回访问未配置错误