Правильный метод для инициализации таблицы базы данных с помощью web2py DAL.define_table () - PullRequest
8 голосов
/ 28 декабря 2011

Я пытаюсь динамически создавать таблицы с именами 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() должен вызываться для каждой визуализации страницы; мое понимание (что его нужно было запустить только один раз, чтобы записать определение таблицы на диск) было неверным.

1 Ответ

5 голосов
/ 28 декабря 2011

Вы можете добавить файл фикстур, который в основном содержит данные по умолчанию, которые будут вставлены один раз при создании таблицы.

Пример приведен здесь: http://thadeusb.com/weblog/2010/4/21/using_fixtures_in_web2py

...