Flask-SQLAlchemy:sqlite3 完整性错误

Mik*_*vin 0 python sqlite sqlalchemy flask flask-sqlalchemy

我正在创建一个应用程序来替换浏览器中当前的选项卡管理器。我在组 - 表主题和选项卡 - 表选项卡之间创建了一个简单的一对多关系。我希望在删除主题时能够自动删除它的子主题。这就是我目前所拥有的:

from flask import request, redirect, url_for, render_template, Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import exc
from flask_whooshee import Whooshee
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
whooshee = Whooshee(app)

@whooshee.register_model('topic_name')
class Topic(db.Model):
    __tablename__ = 'topic'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    topic_name = db.Column(db.String, unique=True, nullable=False)
    topic_created = db.Column(db.DateTime, default=datetime.utcnow)
    topic_changed = db.Column(db.DateTime, default=datetime.utcnow)
    topic_tabs = db.relationship('Tab', backref='topic', cascade='all, delete-orphan', lazy='dynamic')

@whooshee.register_model('tab_name', 'tab_link', 'tab_description')
class Tab(db.Model):
    __tablename__ = 'tab'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    tab_name = db.Column(db.String, nullable=False)
    tab_link = db.Column(db.String, unique=True, nullable=False)
    tab_favicon = db.Column(db.String)
    tab_description = db.Column(db.String)
    tab_created = db.Column(db.DateTime, default=datetime.utcnow)
    tab_changed = db.Column(db.DateTime, default=datetime.utcnow)
    topic_id = db.Column(db.Integer, db.ForeignKey('topic.id'))

@app.route('/', methods=['GET'])
def index():
    return "Test"

if __name__ == '__main__':
    db.create_all()
    try:
        db.session.commit()
    except exc.IntegrityError as e:
        print(str(e))
        db.session.rollback()

    top = Topic(topic_name='Test')
    db.session.add(top)
    try:
        db.session.commit()
    except exc.IntegrityError as e:
        print(str(e))
        db.session.rollback()

    top2 = Topic(topic_name='Test2')
    db.session.add(top2)
    try:
        db.session.commit()
    except exc.IntegrityError as e:
        print(str(e))
        db.session.rollback()

    t1 = Tab(tab_name='t1', tab_link='t1l', tab_favicon='t1f', tab_description='t1d', topic_id=top.id)
    t2 = Tab(tab_name='t2', tab_link='t2l', tab_favicon='t2f', tab_description='t2d', topic_id=top.id)
    t3 = Tab(tab_name='t3', tab_link='t3l', tab_favicon='t3f', tab_description='t3d', topic_id=top.id)

    db.session.add(t1)
    db.session.add(t2)
    db.session.add(t3)
    try:
        db.session.commit()
    except exc.IntegrityError as e:
        print(str(e))
        db.session.rollback()
    import uuid
    app.secret_key = str(uuid.uuid4())
    app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)

问题是,当我尝试在数据库中添加某些内容并且不确定会出现什么问题时,我会遇到完整性错误。如果我停止服务器,我还想在数据库中保存以前的记录,我该如何实现呢?

UPD:即使我完全删除数据库,也会发生以下行为。python script_name.py在空文件夹中运行脚本后,我收到此错误。

UPD2:如果有人需要检查数据库是否存在,有一个特殊的帮助函数https://sqlalchemy-utils.readthedocs.io/en/latest/database_helpers.html#database-exists

(sqlite3.IntegrityError) UNIQUE 约束失败:topic.topic_name [SQL: 'INSERT INTO topic (topic_name, topic_created, topic_changed) VALUES (?, ?, ?)'] [参数:('Test', '2018-09-03 05:21:08.728564', '2018-09-03 05:21:08.728564')] (此错误的背景位于: http: //sqlalche.me/e/gkpj

(sqlite3.IntegrityError) UNIQUE 约束失败:topic.topic_name [SQL: 'INSERT INTO topic (topic_name, topic_created, topic_changed) VALUES (?, ?, ?)'] [参数:('Test2', '2018-09-03 05:21:08.730562', '2018-09-03 05:21:08.730562')] (此错误的背景位于: http: //sqlalche.me/e/gkpj

(sqlite3.IntegrityError) UNIQUE 约束失败:tab.tab_link [SQL: 'INSERT INTO tab (tab_name, tab_link, tab_favicon, tab_description, tab_created, tab_changed, topic_id) VALUES (?, ?, ?, ?, ?, ?, ?) '] [参数:('t1', 't1l', 't1f', 't1d', '2018-09-03 05:21:08.733561', '2018-09-03 05:21:08.733561', 无) ](此错误的背景位于:http://sqlalche.me/e/gkpj

shm*_*mee 5

您的脚本是 WSGI 应用程序,因此运行为__main__. 如果您使用服务器将启动的debug=True参数,请设置 debug mode: on 并重新启动,再次执行该块(每次对脚本进行更改并在服务器运行时保存它时再次执行)。app.run()with stat__name__ == '__main__'

当您在空/已删除的数据库上启动应用程序时,第一次执行该块时,它会创建该数据库并插入您在该块中创建的__name__ == '__main__'两个Topic和三个对象。Tab然后它设置调试模式并重新启动,再次执行该块,尝试第二次插入这五个对象。

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return "Hello, World!"

if __name__ == '__main__':
    print(__name__)
    app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)

输出:

__main__ # <-- fist time around it creates DB and objects
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Restarting with stat # <-- re-executing your script
__main__ # <-- trying to create the same objects again, violating the UNIQUE constraint
 * Debugger is active!
 * Debugger PIN: 302-544-855
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Run Code Online (Sandbox Code Playgroud)