【问题标题】:Flask: application unable to run because of KeyErrorFlask:由于 KeyError,应用程序无法运行
【发布时间】:2018-07-19 07:12:44
【问题描述】:

我目前正在研究如何使用 Flask 开发 Web 应用程序,我正在关注如何使用 this 的教程,一切进展顺利,直到引入了 Flask-SQLAchemy 的概念。

我的烧瓶应用的结构如下

├── bin
├── bookshelf
│   ├── admin
│   │   ├── controllers.py
│   │   ├── __init__.py
│   ├── data
│   │   ├── __init__.py
│   │   ├── models.py
│   ├── __init__.py
│   ├── main
│   │   ├── controllers.py
│   │   ├── __init__.py
│   ├── static
│   └── templates
├── config.py
├── data-dev.sqlite
├── docs
├── requirements.txt
├── run.py

我正在尝试使用我自己设计的 sqlite 数据库(data-dev.sqlite),而无需经历SQLAchemy 为我创建的过程,以下是它的结构;使用 sqlite 中的.dump 命令生成的

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE author (
id INTEGER NOT NULL PRIMARY KEY,
author_names VARCHAR(100) NOT NULL UNIQUE
);
CREATE TABLE book (
id INTEGER NOT NULL PRIMARY KEY,
title VARCHAR(80) NOT NULL,
rating INT,
image VARCHAR(30),
author_id INTEGER NOT NULL,
FOREIGN KEY (author_id) REFERENCES author(id)
);
CREATE TABLE role (
id INTEGER NOT NULL PRIMARY KEY,
role_name VARCHAR(80) NOT NULL UNIQUE,
description VARCHAR(255)
);
CREATE TABLE user (
id INTEGER NOT NULL PRIMARY KEY,
email VARCHAR(75) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
active BOOLEAN NOT NULL DEFAULT 0,
role_id INTEGER NOT NULL,
FOREIGN KEY (role_id) REFERENCES role(id)
);
COMMIT;

我在venv中运行命令python run.py runserver -d时产生的回溯是

Traceback (most recent call last):
  File "run.py", line 1, in <module>
    from bookshelf import create_app
  File "/home/mayatsa/environments/flask-test/bookshelf/__init__.py", line 2, in <module>
    from bookshelf.main.controllers import main
  File "/home/mayatsa/environments/flask-test/bookshelf/main/controllers.py", line 2, in <module>
    from bookshelf.data.models import Author, Book
  File "/home/mayatsa/environments/flask-test/bookshelf/data/models.py", line 6, in <module>
    class Book(db.Model):
  File "/home/mayatsa/environments/flask-test/bookshelf/data/models.py", line 8, in Book
    __table__ = db.Model.metadata.tables['book']
KeyError: 'book'

traceback文件从上到下的顺序及其内容如下

run.py

from bookshelf import create_app
from flask_script import Manager

app = create_app()
manager = Manager(app)

if __name__ == '__main__':
    manager.run()

书架/__init__.py

from flask import Flask
from bookshelf.main.controllers import main
from bookshelf.admin.controllers import admin
from bookshelf.data.models import db

def create_app():
    app = Flask(__name__)
    app.config.from_object('config')

    with app.app_context():
        db.init_app(app)
        db.Model.metadata.reflect(db.engine)

    app.register_blueprint(main, url_prefix='/')
    app.register_blueprint(admin, url_prefix='/admin')

    return app

bookshelf/main/controllers.py

from flask import Blueprint, render_template, request
from bookshelf.data.models import Author, Book

main = Blueprint('main', __name__, template_folder='templates')

@main.route('/')
def index():
    return render_template('main/index.html')

@main.route('books/')
def display_books():
    return render_template('main/books.html')

bookshelf/data/models.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Book(db.Model):
    __table__ = db.Model.metadata.tables['book']
    def __repr__(self):
        return '<Book %r>' % (self.title)

class Author(db.Model):
    __table__ = db.Model.metadata.tables['author']
    def __repr__(self):
        return '<Author %r>' % (self.author_names)

class Role(db.Model):
    __table__ = db.Model.metadata.tables['role']
    def __repr__(self):
        return '<Role %r>' % (self.role_name)

class User(db.Model):
    __table__ = db.Model.metadata.tables['user']

    def __repr__(self):
        return '<User %r>' % (self.email)

附加config.py

import os
basedir = os.path.abspath(os.path.dirname(__file__))

DEBUG = True
TESTING = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
    'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = 'a9eec0e0-23b7-4788-9a92-318347b9a39f'

根据上面提供的所有代码,是什么导致我的应用程序产生此错误并阻止它运行? 谢谢

【问题讨论】:

    标签: python python-3.x flask flask-sqlalchemy


    【解决方案1】:

    我一直在探索,直到我登陆 this questionthis one,他们帮助我消除了迷雾。

    安装sqlacodegenflask-sqlacodegen后使用

    pip install sqlacodegen
    pip install flask-sqlacodegen
    

    我现在要做的就是在我的 Flask 应用程序根目录中运行以下命令

    sqlacodegen sqlite:///data-dev.sqlite --flask > models.py
    

    并且生成了与我的数据库对应的模型,然后在我将bookshelf/data/models.py 替换为刚刚生成的models.py 之后。

    然后终于把bookshelf/__init__.pycreate_app函数改成这个样子

    def create_app():
        app = Flask(__name__)
        app.config.from_object('config')
    
        db.init_app(app)
    
        app.register_blueprint(main, url_prefix='/')
        app.register_blueprint(admin, url_prefix='/admin')
    
        return app
    

    现在一切似乎都正常了。

    【讨论】:

      【解决方案2】:

      在您导入 bookshelf.data.models 时元数据还不存在,因为它只是在之后才反映到元数据中。

      也许使用__tablename__ 而不是__table__ 可能会有所帮助?我不太熟悉 SQLAlchemy 的复杂性。

      【讨论】:

      • 它仍然产生相同的输出
      • 如果你使用__tablename__ = 'book',例如?
      • 当我这样做时,它会给我这个消息sqlalchemy.exc.ArgumentError: Mapper Mapper|Book|book could not assemble any primary key columns for mapped table 'book'
      猜你喜欢
      • 1970-01-01
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-23
      相关资源
      最近更新 更多