db.create_all() 在磁盘上但不在内存中创建模式
Posted
技术标签:
【中文标题】db.create_all() 在磁盘上但不在内存中创建模式【英文标题】:db.create_all() Creates Schema on Disk But Not in Memory 【发布时间】:2021-11-12 18:08:24 【问题描述】:我正在尝试按照 Harry Percival 书中的模式为我正在编写的 Flask 联系人管理器应用程序开发功能/集成测试。为了测试,我想创建一个 sqlite3 内存数据库,但对 db.create_all()
的调用不会创建我的模式,即使相同的调用适用于磁盘上的 sqlite3 数据库。我的代码:
config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'Hard to guess string'
SQLALCHEMY_TRACK_MODIFICATIONS = False
LOG_TO_STDOUT = False
@staticmethod
def init_app(app):
pass
class TestConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
SQLALCHEMY_TRACK_MODIFICATIONS = True
class DevConfig(Config):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'database.db')
SQLALCHEMY_TRACK_MODIFICATIONS = True
config =
'development': DevConfig,
'testing': TestConfig,
'default': DevConfig
app/__init__.py
import os
from flask import Flask
from flask_bootstrap import Bootstrap
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
import logging
from logging.handlers import RotatingFileHandler
from config import config
db = SQLAlchemy()
migrate = Migrate()
bootstrap = Bootstrap()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
migrate.init_app(app, db)
bootstrap.init_app(app)
from app.main import main as main_blueprint
app.register_blueprint(main_blueprint)
from app.contacts import contacts as contacts_blueprint
app.register_blueprint(contacts_blueprint, url_prefix='/contacts')
from app.auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix='/auth')
if app.config['LOG_TO_STDOUT']:
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
app.logger.addHandler(stream_handler)
else:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/contacts.log', maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.DEBUG)
app.logger.info('Contacts startup')
return app
from app import models
functional_tests.py
import unittest
from flask_testing import LiveServerTestCase
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from app import create_app, db
from app.models import Contact
class NewVisitorTest(LiveServerTestCase):
def create_app(self):
# app = create_app('development')
app = create_app('testing')
return app
def setUp(self):
self.app = self.create_app()
self.browser = webdriver.Firefox()
db.create_all()
def tearDown(self):
self.browser.quit()
db.session.remove()
db.drop_all()
def test_can_enter_new_contact_and_retreive_it_later(self):
# Edith has recently joined the IBS Communications Committee, and wants to look
# up information on one of the Society's contacts.
# She has been told about the Contact Manager application, and decides to try it
# out. She attempts to access the application.
self.browser.get(self.get_server_url())
# testing fails, development succeeds
当我使用development
配置运行此测试时,该配置使用磁盘上的sqlite 数据库,db.create_all()
成功并且测试通过;当我使用testing
配置时,它会失败并显示以下回溯:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: contacts
[SQL: SELECT contacts.id AS contacts_id, contacts.email AS contacts_email, contacts.firstname AS contacts_firstname, contacts.lastname AS contacts_lastname, contacts.phone AS contacts_phone, contacts.seller_id AS contacts_seller_id, contacts.blacklisted AS contacts_blacklisted, contacts.disabled AS contacts_disabled, contacts.is_member AS contacts_is_member, contacts.membership_date AS contacts_membership_date
FROM contacts ORDER BY contacts.id ASC]
(Background on this error at: https://sqlalche.me/e/14/e3q8)
我检查了SQLALCHEMY_ECHO = True
,SQLAlchemy 正在生成完整的CREATE TABLE
语句集,以COMMIT
结尾,并且生成的 SQL 在测试用例之间是相同的。
【问题讨论】:
有人投票决定关闭,因为我的问题“缺乏调试细节”。也许你可以告诉我你还想要什么其他细节? 也许显示你的工厂函数'create_app',看看你是如何实例化db对象的,它用简单的话告诉你它没有找到表的错误,所以你的模型可能不是测试前被db对象发现 @SebastianSalinasDelRio 我已按您的要求添加了我的app/__init__.py
文件。令人气愤的是,当我将测试数据库更改为磁盘数据库时,整个事情就开始工作了,但是如果我切换回内存,它仍然无法工作,即使它在我所有其他教程中都有效完毕。不过,这只是一种解决方法,我非常喜欢一个实际的解决方案。
据我所知,您的导入存在问题,主要是在 init.py 中,您在文件底部导入模型,我复制了一个 mini您的应用程序的版本,我收到很多导入错误。所以我推荐以下提示:从__init__.py
提取db
对象,以便您可以安全地导入它 创建一个应用程序运行器并在那里建立迁移扩展 导入您的模型在您的 create_app 功能之前如果您需要更多帮助,我们可以更广泛地交谈。
@SebastianSalinasDelRio 这不会导致磁盘数据库出现同样的问题吗?它没有。
【参考方案1】:
错误出现在您的 DATABASE URI 中,在 TestConfig
类上,为了在内存数据库中建立临时性,正确的 URI 是:'sqlite://'
NOT 'sqlite:///:memory:'
。
您好!
【讨论】:
那行不通。 我的内存测试使用'sqlite://'。你看到了什么错误? 无论我使用sqlite://
还是sqlite:///:memory:
,都会看到与上面显示的完全相同的错误。以上是关于db.create_all() 在磁盘上但不在内存中创建模式的主要内容,如果未能解决你的问题,请参考以下文章
SSLHandshakeException CertPathValidatorException 在 Android 2.3 上但不在 Android 4 上