【发布时间】:2011-12-28 00:18:17
【问题描述】:
我正在尝试使用完全相同的 SQL 定义动态构建名为 db.blog 和 db.code 的表。在我定义它们之后,我想用 10 行随机数据填充它们,并且不再执行该初始化代码。
我的问题是,当我查看db.code 或db.blog 的newblog appadmin 界面时,每次在浏览器上点击刷新时都会执行初始化代码:https://172.25.1.1/newblog/appadmin/select/db?query=db.code.id>0
我在newblog/models/newblog.py中初始化db.blog和db.code:
from gluon import *
from gluon.contrib.populate import populate
## initialize db.blog and db.code:
## At runtime, build TAGGED_TABLES (once)
TAGGED_TABLES = set(['blog', 'code'])
for tt in TAGGED_TABLES:
if not db.get(tt, False):
db.define_table(tt,
Field('name', length=32, notnull=True),
Field('value', length=65535, notnull=True),
Field('tags', type='list:reference tag', unique=False, notnull=False),
)
populate(db.get(tt), 10)
## cross-reference db.tagged_tables to this one
db.tagged_tables.insert(name=tt,
database_pointer='reference %s' % tt)
db.commit()
不知何故,if not db.get(tt, False): 允许多次执行它下面的例程。我不明白为什么...如果表已经创建,那么not db.get(tt, False) 应该是False。但是,web2py 从不跳过初始化代码,这意味着 db.blog 和 db.code 在每次重新加载时增加 10 个条目。
问题:为什么if not db.get(tt, False): 不能防止多次执行?
我在 Debian 6.0 / sqlite 3.7.3 / Cherokee 1.2.101 / uWSGI 0.9.9.3 上运行 web2py 1.99.4
解决方案
根据 Interrobang 的回答,正确的写法是:
from gluon import *
from gluon.contrib.populate import populate
TAGGED_TABLES = set(['blog', 'code'])
for tt in TAGGED_TABLES:
# db.define_table() must be called on **every page**
# this sets things up in memory...
db.define_table(tt,
Field('name', length=32, notnull=True),
Field('value', length=65535, notnull=True),
Field('tags', type='list:reference tag', unique=False, notnull=False),
)
## initialize db.blog and db.code:
## At runtime, populate tables named in TAGGED_TABLES (once)
if not (db(db.get(tt).id>0).select()):
populate(db.get(tt), 10)
## cross-reference db.tagged_tables to this table (named in var tt)
db.tagged_tables.insert(name=tt,
database_pointer='reference %s' % tt)
db.commit()
现在db.blog 和db.code 的大小保持不变。
总结
每次页面渲染都必须调用db.define_tables();我的理解(它只需要运行一次就可以将表定义写入磁盘)是不正确的。
【问题讨论】:
-
+1 以获得很好的解决方案总结。
-
@Interrobang,谢谢。我也投了赞成票。您的理解是正确完成这项工作的关键