【问题标题】:Using a test peewee database instance in a Flask app在 Flask 应用程序中使用测试 peewee 数据库实例
【发布时间】:2024-04-22 22:15:01
【问题描述】:

我想用测试数据运行我的网站(目前使用 Flask 服务器运行)。我正在使用我从测试中初始化的 peewee 数据库代理。我的模型是:

database_proxy = Proxy()


class MySQLModel(Model):
    """ A base model that will use our MySQL database """

    class Meta:
        database = database_proxy


class Person(MySQLModel):
    id = PrimaryKeyField(primary_key=True)
    name = CharField()

在测试过程中,我新建了一个内存数据库:

test_db = SqliteDatabase(':memory:')

并初始化模型的数据库:

database_proxy.initialize(test_db)
if database_proxy.is_closed():
    database_proxy.connect()
Person.create_table()

然后我创建数据并运行我的 Flask 服务器:

app = Flask(__name__)
app.run(debug=True)

我的一条路线选择了我数据库中的所有人员。但这会引发异常,说表 Person 不存在。对于好奇的人,功​​能是:

@app.route("/api/people")
def list_people():
    ppl = models.Person.select(models.Person.id).dicts().execute()
    [ ... formatting and returning a json ... ]

如果我在服务器外部运行相同的查询,它当然可以工作。

我确保我的 Flask 应用程序使用相同的数据库实例,通过调试并查看模型 Person 在我的测试和 Flask 函数中使用相同的 SqliteDatabase 对象(我检查了内存地址是否相同)。

这里发生了什么?当我在烧瓶中查询数据时,我的数据在哪里?

示例调试运行:

[在运行 app.run() 之前]

>>> models.Person.get()
<database.models.Person object at 0x7f8dde8e09d0>
>>> models.Person._meta.database.obj
<peewee.SqliteDatabase object at 0x7f8dde8e0190>

[在 app.run() 之后]

* Debugger is active!
 * Debugger pin code: 327-505-347
127.0.0.1 - - [03/May/2016 16:36:12] "GET / HTTP/1.1" 200 -
... Loads more pages ...
>>> models.Person._meta.database.obj
<peewee.SqliteDatabase object at 0x7f8dde8e0190>
>>> models.Person.get()
Traceback (most recent call last):
  File "/home/q/Software/pycharm-2016.1.2/helpers/pydev/_pydevd_bundle/pydevd_exec.py", line 3, in Exec
    exec exp in global_vars, local_vars
  File "<input>", line 1, in <module>
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 4505, in get
    return sq.get()
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 2885, in get
    return next(clone.execute())
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 2932, in execute
    self._qr = ResultWrapper(model_class, self._execute(), query_meta)
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 2628, in _execute
    return self.database.execute_sql(sql, params, self.require_commit)
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 3461, in execute_sql
    self.commit()
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 3285, in __exit__
    reraise(new_type, new_type(*exc_args), traceback)
  File "/home/q/dev/dev/venv/local/lib/python2.7/site-packages/peewee.py", line 3454, in execute_sql
    cursor.execute(sql, params or ())
OperationalError: no such table: person

【问题讨论】:

    标签: python database testing flask peewee


    【解决方案1】:

    从未使用过 Flask,但该应用程序在启动时可以初始化不同的数据库吗?我没有看到你在哪里告诉 Flask 关于新数据库的信息,这让我感到奇怪。

    您能否在 Flask 初始化过程中创建数据库条目(在您调用 app = Flask(__name__) 之后?请查看 this peewee example

    【讨论】:

    • 我不确定你是否读过我的问题,因为我已经展示了 DB 对象是同一个 DB 对象,而且无论如何我的 Web 服务器没有初始化任何数据库,它使用我初始化的那个为了它。无论如何,我已经解决了这个问题并回答了这个问题
    • 你是对的。我错过了你已经验证了内存地址。只是想为您提供一条途径,因为没有其他人提供回应。
    【解决方案2】:

    我没有深入研究 peewee 的实现,但我的猜测是这个问题是由 peewee 中的一些线程管理机制引起的,至少对于 Sqlite 内存数据库来说是这样。也许它把东西保存在 TLS 中。

    使用文件数据库代替内存数据库可以解决这个问题。

    【讨论】:

      最近更新 更多