Web2py 数据库:如何 select 来自 selected 行的行子集?我如何将它传递给 JavaScript?
Web2py databases: How do I select a subset of rows from selected rows? And how do I pass it to JavaScript?
我有一个 table 并希望 web2py 操作将其所有内容传递给视图。然后视图 select 是它的一个子集,并在迭代中一次显示一个。
这是 db.py 中的示例 table:
db.define_table('block',
Field('location'),
Field('propertyA'),
Field('propertyB')
)
控制器中的示例操作 default.py:
def demo():
return dict(blocks=db(db.block).select())
到目前为止一切顺利。它可以编译,不会崩溃,并且在 运行 进行了几次测试后,它达到了我想要的效果。
但现在来看。在这个例子中,我想 select 所有 "propertyA" 是 5 的人。然后我想 运行 一个循环,将它们打印到 table ,它已经存在。 table 有 100 个单元格,id 为 1-100。我想将 propertyB 的值打印到 table 个单元格,其 ID 与块的位置匹配。
示例视图 default/demo.html:
{{extend 'layout.html'}}
<style>
table#map, td {
border: 1px solid black;
border-collapse: collapse;
}
td {
background-color: gray;
width: 50px;
height:50px;
text-align: center;
color: white;
}
</style>
<!--This creates a 10*10 table with running id from 1 to 100-->
<table id="map">
<caption>Map</caption>
{{for y in range(10):}}
<tr>
{{for x in range(10):}}
{{=TD('', _id=10*y+x)}}
{{pass}}
</tr>
{{pass}}
</table>
<!--then I want to select a subset from blocks, whose propertyA is 5
These lines crash if uncommented.-->
{{#query = (propertyA == 5)}}
{{#subset = blocks(query).select()}}
<!--and run a loop which, which iterates the subset, and in each
iteration, writes the value of propertyB, if cell's id and block's location
match. I just made a place holder function, because I don't know how to
pass python variables/objects to javascript-->
<script>
//var subset = "subset from python";
function myFunction() {
var i;
for (i = 0; i < 100; i++) {
//var cell = document.getElementById(i);
//if(subset(location===cell.id).select() === True) {
//var value = subset(location===cell.id).propertyB;
//cell.innerHTML = value;
//} else {
//cell.innerHTML = '';
//}
}
}
</script>
所以我不知道应该怎么做。而 web2py 教程书对这方面的信息非常吝啬。还是我对此采取了完全错误的方法?因为我认为它也可以通过 ajax 调用来完成,但我不认为连续 100 次对数据库服务器进行查询是正确的做法。
.select
是 DAL Set
对象和 returns 一个 Rows
对象的方法——您不能再将 .select
方法应用到Rows
对象。相反,Rows
对象有一个 .find
方法,returns 一个新的过滤 Rows
对象:
blocks.find(lambda row: row.propertyA == 5)
如果要使用Javascript中propertyA值的子集,需要将其写入模板中的Javascript代码中。首先,您必须将每一行中的各个值提取到列表中,然后将其转换为 JSON 以便将其用作 Javascript 变量:
{{from gluon.serializers import json}}
<script>
var subset = {{=json([r.propertyA for r in blocks if r.propertyA == 5])}}
</script>
这里我们简单地使用模板分隔符({{ }}
)将Python代码的结果直接写到Javascript代码中,以便定义[=的值21=]变量。
另外,请注意,由于使用了列表推导式来生成 propertyA 值的列表,因此可以使用 if
子句来过滤记录,而不是使用 .find
方法。
通常最好尽量减少视图中的 Python 逻辑量(更难阅读、调试和测试),因此最好创建所有 JSON 数组在控制器中并简单地将它们传递给视图。
此外,如果 blocks
中的记录数量很大,在 Python 中进行过滤可能会很慢,因此对每个需要的子集进行单独的数据库查询最终可能会更快,而不是而不是仅在 Python 中执行单个查询并从中构建子集(特别是如果每个子集需要数据库中的不同字段 table - 这样您就可以将每个查询限制为仅需要的字段,这将进一步提高性能)。也许现在不值得担心,但如果性能成为问题,您可以进行一些分析以确定最佳方法。
我有一个 table 并希望 web2py 操作将其所有内容传递给视图。然后视图 select 是它的一个子集,并在迭代中一次显示一个。
这是 db.py 中的示例 table:
db.define_table('block',
Field('location'),
Field('propertyA'),
Field('propertyB')
)
控制器中的示例操作 default.py:
def demo():
return dict(blocks=db(db.block).select())
到目前为止一切顺利。它可以编译,不会崩溃,并且在 运行 进行了几次测试后,它达到了我想要的效果。
但现在来看。在这个例子中,我想 select 所有 "propertyA" 是 5 的人。然后我想 运行 一个循环,将它们打印到 table ,它已经存在。 table 有 100 个单元格,id 为 1-100。我想将 propertyB 的值打印到 table 个单元格,其 ID 与块的位置匹配。
示例视图 default/demo.html:
{{extend 'layout.html'}}
<style>
table#map, td {
border: 1px solid black;
border-collapse: collapse;
}
td {
background-color: gray;
width: 50px;
height:50px;
text-align: center;
color: white;
}
</style>
<!--This creates a 10*10 table with running id from 1 to 100-->
<table id="map">
<caption>Map</caption>
{{for y in range(10):}}
<tr>
{{for x in range(10):}}
{{=TD('', _id=10*y+x)}}
{{pass}}
</tr>
{{pass}}
</table>
<!--then I want to select a subset from blocks, whose propertyA is 5
These lines crash if uncommented.-->
{{#query = (propertyA == 5)}}
{{#subset = blocks(query).select()}}
<!--and run a loop which, which iterates the subset, and in each
iteration, writes the value of propertyB, if cell's id and block's location
match. I just made a place holder function, because I don't know how to
pass python variables/objects to javascript-->
<script>
//var subset = "subset from python";
function myFunction() {
var i;
for (i = 0; i < 100; i++) {
//var cell = document.getElementById(i);
//if(subset(location===cell.id).select() === True) {
//var value = subset(location===cell.id).propertyB;
//cell.innerHTML = value;
//} else {
//cell.innerHTML = '';
//}
}
}
</script>
所以我不知道应该怎么做。而 web2py 教程书对这方面的信息非常吝啬。还是我对此采取了完全错误的方法?因为我认为它也可以通过 ajax 调用来完成,但我不认为连续 100 次对数据库服务器进行查询是正确的做法。
.select
是 DAL Set
对象和 returns 一个 Rows
对象的方法——您不能再将 .select
方法应用到Rows
对象。相反,Rows
对象有一个 .find
方法,returns 一个新的过滤 Rows
对象:
blocks.find(lambda row: row.propertyA == 5)
如果要使用Javascript中propertyA值的子集,需要将其写入模板中的Javascript代码中。首先,您必须将每一行中的各个值提取到列表中,然后将其转换为 JSON 以便将其用作 Javascript 变量:
{{from gluon.serializers import json}}
<script>
var subset = {{=json([r.propertyA for r in blocks if r.propertyA == 5])}}
</script>
这里我们简单地使用模板分隔符({{ }}
)将Python代码的结果直接写到Javascript代码中,以便定义[=的值21=]变量。
另外,请注意,由于使用了列表推导式来生成 propertyA 值的列表,因此可以使用 if
子句来过滤记录,而不是使用 .find
方法。
通常最好尽量减少视图中的 Python 逻辑量(更难阅读、调试和测试),因此最好创建所有 JSON 数组在控制器中并简单地将它们传递给视图。
此外,如果 blocks
中的记录数量很大,在 Python 中进行过滤可能会很慢,因此对每个需要的子集进行单独的数据库查询最终可能会更快,而不是而不是仅在 Python 中执行单个查询并从中构建子集(特别是如果每个子集需要数据库中的不同字段 table - 这样您就可以将每个查询限制为仅需要的字段,这将进一步提高性能)。也许现在不值得担心,但如果性能成为问题,您可以进行一些分析以确定最佳方法。