1

我有一个表,并希望 web2py 操作将其所有内容传递给视图。然后视图从中选择一个子集,并在迭代中一次显示一个。

这是 db.py 中的示例表:

db.define_table('block',
    Field('location'),
    Field('propertyA'),
    Field('propertyB')
)

控制器 default.py 中的示例操作:

def demo():
    return dict(blocks=db(db.block).select())

到目前为止,一切都很好。它可以编译,不会崩溃,并且在运行了一些测试后它做了我想要的。

但现在来看。在这个例子中,我想选择所有的“propertyA”,比如说,5。然后我想运行一个循环,将它们打印到一个已经存在的表中。该表有 100 个单元格,ID 为 1-100。我想将 propertyB 的值打印到表单元格中,其 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 次查询数据库服务器是正确的做法。

4

1 回答 1

0

.select是一个 DALSet对象的方法并返回一个Rows对象——然后您不能.select再次将该方法应用于该Rows对象。相反,该Rows对象有一个.find方法,该方法返回一个新的过滤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 代码,以便定义subset变量的值。

另外,请注意,因为列表推导式用于生成 propertyA 值的列表,所以可以使用if子句过滤记录而不是使用.find方法。

通常最好尽量减少视图中 Python 逻辑的数量(更难阅读、调试和测试),因此最好在控制器中创建所有 JSON 数组并将它们简单地传递给视图。

此外,如果其中的记录数量blocks很大,则 Python 中的过滤可能会很慢,因此为所需的每个子集执行单独的数据库查询最终可能会更快,而不是仅在 Python 中执行单个查询并从该子集构建子集(特别是如果每​​个子集都需要数据库表中的不同字段——这样您可以将每个查询限制为仅需要的字段,这将进一步提高性能)。也许现在不值得担心,但如果性能成为问题,您可以进行一些分析以确定最佳方法。

于 2015-07-22T14:38:02.273 回答