使用 web2py DAL.define_table() 初始化数据库表的正确方法

发布于 2024-12-23 03:15:59 字数 2606 浏览 1 评论 0原文

我正在尝试使用完全相同的 SQL 定义动态构建名为 db.blogdb.code 的表。定义它们后,我想用 10 行随机数据填充它们,并且不再执行该初始化代码。

我的问题是,当我查看 db.codedb.blog 的 newblog appadmin 界面时,每次在浏览器上刷新时都会执行初始化代码:https://172.25.1.1/newblog/appadmin/select/db?query=db.code.id>0

我初始化 db.blog 和 < newblog/models/newblog.py 中的 code>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.blogdb.code 保持恒定大小。

总结

每次页面渲染都必须调用db.define_tables();我的理解(它只需要运行一次即可将表定义写入磁盘)是不正确的。

I am trying to dynamically build tables called db.blog and db.code with exactly the same SQL definitions. After I define them, I want to populate them with 10 rows of random data, and never execute that initialization code again.

My problem is that the initialization code executes every time I hit refresh on the browser while I view the newblog appadmin interface for db.code or db.blog: https://172.25.1.1/newblog/appadmin/select/db?query=db.code.id>0

I initialize db.blog and db.code in newblog/models/newblog.py:

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()

Somehow if not db.get(tt, False): allows multiple executions of the routine below it. I don't understand why... if the table has already been created, then not db.get(tt, False) should be False. However, web2py never skips the initialization code, which means db.blog and db.code grow by 10 entries on each reload.

Question: Why isn't if not db.get(tt, False): preventing multiple executions?

I am running web2py 1.99.4 on Debian 6.0 / sqlite 3.7.3 / Cherokee 1.2.101 / uWSGI 0.9.9.3

Solution

Based on Interrobang's answer the correct way to write this is:

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()

Now db.blog and db.code stay a constant size.

Summary

db.define_tables() must be called for every page rendering; my understanding (that it only needed to run once to write the table definition to disk) was incorrect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温柔戏命师 2024-12-30 03:15:59

您可以添加一个固定文件,它基本上包含创建表时要插入一次的默认数据。

这里给出了一个例子: http://thadeusb.com/weblog/2010/4/21 /using_fixtures_in_web2py

You can add a fixtures file, which basically contains default data to be inserted once, when the table is created.

An example is given here: http://thadeusb.com/weblog/2010/4/21/using_fixtures_in_web2py

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文