Я пытаюсь динамически создавать таблицы с именами db.blog
и db.code
с точно такими же определениями SQL. После того как я определю их, я хочу заполнить их 10 строками случайных данных и больше никогда не выполнять этот код инициализации.
Моя проблема заключается в том, что код инициализации выполняется каждый раз, когда я нажимаю кнопку обновления в браузере, пока я просматриваю интерфейс newblog appadmin для db.code
или db.blog
: https://172.25.1.1/newblog/appadmin/select/db?query=db.code.id>0
Я инициализирую db.blog
и db.code
в 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()
Каким-то образом if not db.get(tt, False):
допускает многократное выполнение подпрограммы под ним. Я не понимаю, почему ... если таблица уже создана, то not db.get(tt, False)
должно быть False
. Однако web2py никогда не пропускает код инициализации, что означает, что db.blog
и db.code
увеличиваются на 10 записей при каждой перезагрузке.
Вопрос: Почему if not db.get(tt, False):
не предотвращает многократное выполнение?
Я использую web2py 1.99.4 в Debian 6.0 / sqlite 3.7.3 / Cherokee 1.2.101 / uWSGI 0.9.9.3
Решение
Основываясь на ответе 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()
должен вызываться для каждой визуализации страницы; мое понимание (что его нужно было запустить только один раз, чтобы записать определение таблицы на диск) было неверным.