【发布时间】:2020-02-23 03:40:47
【问题描述】:
我在 heroku 上部署了这段代码,我正在使用 CI/CD 与 travis 和 heroku。出于开发原因,我正在使用 SQLite 数据库。我希望每次在 heroku 上部署 repo 时,数据库将被删除并使用文件数据再次创建。我这样做了,但是 heroku 给了我标题错误。
这是我的代码:
初始化.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
import os
db = SQLAlchemy()
def create_app(conf_test=None):
app = Flask(__name__, instance_relative_config=True)
print("instance path --- " + os.path.join(app.instance_path, 'database.db'))
app.config.from_mapping(
SQLALCHEMY_DATABASE_URI = ''.join(['sqlite:////', os.path.join(app.instance_path, 'database.db')]),
SQLALCHEMY_TRACK_MODIFICATIONS = os.environ['SQLALCHEMY_TRACK_MODIFICATIONS'],
JWT_KEY = os.environ['JWT_KEY'],
SECRET_KEY = os.environ['SECRET_KEY']
)
if conf_test is not None:
app.config.update(conf_test)
from .model import init_db
with app.app_context(): init_db()
from .views import init_views
with app.app_context(): init_views()
@app.route("/")
def hello():
return "it's working..."
return app
模型.py
class CurrentState(enum.Enum):
available = 'AVAILABLE'
in_progress = 'IN PROGRESS'
finished = 'FINISHED'
thesis_have_keywords = db.Table('thesis_have_keywords',
db.Column('thesis_id', db.Integer, db.ForeignKey("thesis.id")),
db.Column('keyword_id', db.Integer, db.ForeignKey("keyword.id"))
)
thesis_have_teaching = db.Table('thesis_have_teaching',
db.Column('thesis_id', db.Integer, db.ForeignKey("thesis.id")),
db.Column('teaching_id', db.Integer, db.ForeignKey("teaching.id"))
)
thesis_have_courses = db.Table('thesis_have_courses',
db.Column('thesis_id', db.Integer, db.ForeignKey("thesis.id")),
db.Column('course_id', db.Integer, db.ForeignKey("degree_courses.id"))
)
class Teacher(db.Model):
name = db.Column(db.String(50), unique=False, nullable=False)
surname = db.Column(db.String(50), unique=False, nullable=False)
mail = db.Column(db.String(100), unique=True, nullable=False)
id = db.Column(db.String(100), unique=True, nullable=False, primary_key=True)
thesis = db.relationship("Thesis", back_populates="teacher")
class Thesis(db.Model):
title = db.Column(db.String(150), unique=True, nullable=False)
description = db.Column(db.Text, unique=False, nullable=False)
last_modify = db.Column(db.DateTime(timezone=True), unique=False, nullable=False, default=datetime.datetime.utcnow)
duration = db.Column(db.Integer, unique=False, nullable=True)
start_time = db.Column(db.DateTime(timezone=True), unique=False, nullable=True)
end_time = db.Column(db.DateTime(timezone=True), unique=False, nullable=True)
current_state = db.Column(db.Enum(CurrentState), unique=False, nullable=False, default=CurrentState('AVAILABLE'))
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
teacher_id = db.Column(db.Integer, db.ForeignKey("teacher.id"))
teacher = db.relationship("Teacher", back_populates="thesis")
keywords = db.relationship("Keyword", back_populates="thesis", secondary=thesis_have_keywords)
teaching = db.relationship("Teaching", back_populates="thesis", secondary=thesis_have_teaching)
courses = db.relationship("DegreeCourses", back_populates="thesis", secondary=thesis_have_courses)
class Keyword(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
thesis = db.relationship("Thesis", back_populates="keywords", secondary=thesis_have_keywords)
class Teaching(db.Model):
name = db.Column(db.String(50), unique=False, nullable=False)
code = db.Column(db.String(100), unique=True, nullable=False)
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
thesis = db.relationship("Thesis", back_populates="teaching", secondary=thesis_have_teaching)
class DegreeCourses(db.Model):
name = db.Column(db.String(50), unique=False, nullable=False)
code = db.Column(db.String(100), unique=True, nullable=False)
_type = db.Column(db.String(20), unique=False, nullable=False)
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
thesis = db.relationship("Thesis", back_populates="courses", secondary=thesis_have_courses)
def init_db():
with current_app.app_context():
if os.path.exists(current_app.instance_path):
shutil.rmtree(current_app.instance_path)
try:
os.makedirs(current_app.instance_path)
except OSError:
pass
db.init_app(current_app)
db.drop_all()
db.session.commit()
db.create_all()
with open("server/teachers.json") as teach_file:
data = json.load(teach_file)
teacher_entries=[]
for teacher in data['teachers']:
teach = Teacher(name=teacher['name'], surname=teacher['surname'], mail=teacher['mail'], id=teacher['id'])
teacher_entries.append(teach)
db.session.add_all(teacher_entries)
db.session.commit()
每次我删除实例文件夹并重新创建它时。我也尝试只删除数据库文件,但出现同样的错误。
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table thesis_have_keywords 已经存在
【问题讨论】:
-
“每次我删除实例文件夹”是什么意思? SQLite 和 Heroku 不能很好地结合在一起,但也可能存在其他问题。
-
对不起我的英语,我的意思是每次我部署一个存储库时,我都会删除所有实例存储库,然后我重新创建它。我知道 sqlite 不是最佳选择,但由于外部原因,我必须使用它。仅出于开发原因。但是每次部署时,heroku 都会给我这个错误。
-
有充分的理由不在 Heroku 上使用 SQLite。您的数据会经常丢失(不仅仅是在部署时)。但是我仍然不确定“我删除所有实例存储库然后我重新创建它”是什么意思。你在运行什么命令?在哪里?
-
我猜这个代码。
if os.path.exists(current_app.instance_path): shutil.rmtree(current_app.instance_path)。抱歉,我的意思是我每次部署代码时都会删除实例文件夹。我也尝试只删除 database.db 文件,但我也遇到了同样的问题。 -
你不应该手动删除任何东西,你尤其是不应该在这样的应用程序代码中这样做。当您部署到 Heroku 时,您每次都会获得一个全新的环境(尽管使用一些构建包,您可能能够缓存库)。
标签: python-3.x sqlite heroku flask flask-sqlalchemy