Flask-Migrate无法检测现有数据库表问题求助
问题:Flask-Migrate无法识别已存在的数据库表
跟着教程学习数据库迁移,执行flask db init命令后成功生成migrations文件夹,但运行flask db migrate -m 'Initial_Migration'时,无法检测到数据库中已存在的表,导致迁移脚本尝试创建models.py中的所有表,执行flask db upgrade时因尝试创建已存在的表报错。
models.py部分代码
# Third-party libraries from sqlalchemy import Table, Column, Integer, String, Boolean, DateTime, ForeignKey, inspect, exc from sqlalchemy.orm import relationship from flask_login import UserMixin from . import basic_functions as bf import os cfg = __import__(os.environ['CONFIG_NAME']) # Equal to "import config as cfg" from . import db #Set up logger database_manager_logger = bf.create_logger('data_base_manager') #Create all tables class TopicSubscription(db.Model): __tablename__="TopicSubscription" #We set our own name because otherwise a name is chosen according to SQLAlchemy conventions which can lead to errors (Table name is used for foreign keys) id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('User.id')) #Note this is referring to the table name, not the class name! topic_id = Column(Integer, ForeignKey('Topic.id')) class User(db.Model,UserMixin): # id = Column(CHAR(21), primary_key=True) __tablename__ = "User" id = Column(Integer, primary_key=True) name = Column(String(80), unique=True, nullable=False) email = Column(String(120), unique=True, nullable=False) nickname = Column(String(80), unique=True, nullable=True) profile_pic = Column(String(200), unique=True, nullable=True) last_send_date = Column(DateTime) #Last time a mail was sent to the user. topics = relationship('Topic', secondary=TopicSubscription.__table__, back_populates="users") # Allows to access topics that this user subscribed to through the junction table TopicSubscription subscribed_questions = relationship("QuestionSubscription", primaryjoin="User.id==QuestionSubscription.user_id") class Topic(db.Model): __tablename__ = "Topic" id = Column(Integer, primary_key=True) topic = Column(String(80)) #The topic name active = Column(Boolean, default=False) users = relationship('User', secondary=TopicSubscription.__table__, back_populates = "topics") #This back_populates refers to the "topics" attribute on the User object. # subscriptions = relationship("TopicSubscription", cascade="all, delete-orphan") #Seems like this is not used, delete it? questions = relationship("Question", cascade="all, delete-orphan")
初始化Flask-Migrate的__init__.py文件(重点查看initialize_database函数)
import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_login import LoginManager import time ####################### #### Configuration #### ####################### # Initialize the database, login_manager and the app variables in the global scope so they are accessible everywhere. db = SQLAlchemy() from project.models import * #Define all tables, must be done at module level for some reason login_manager = LoginManager() app = None #Initialize the global app variable ###################################### #### Application Factory Function #### ###################################### def create_app(config_filename=None): global app #Declare the app as global else it is not accessible for other modules. app = Flask(__name__, instance_relative_config=True) app.config.from_pyfile(config_filename) # Load the config file app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24) initialize_database(app) register_blueprints(app) start_scheduler() return app ########################## #### Helper Functions #### ########################## def initialize_database(app): # Since the application instance is now created, pass it to each Flask # extension instance to bind it to the Flask application instance (app) db.init_app(app) with app.app_context(): db.engine.dialect.supports_sane_rowcount = db.engine.dialect.supports_sane_multi_rowcount = False # Otherwise there's an error when deleting topics retry_database_connect(nr_of_retries=50) migrate = Migrate(app, db) # This makes sure that any database changes are migrated. def retry_database_connect(nr_of_retries:int): """Connects to the database, catching errors and re-trying for 25 seconds.""" connection_error = True counter = 0 while (connection_error == True and counter < nr_of_retries): try: # This has to be run before the creation of all tables, otherwise the newly created tables are deleted and there are zero tables to work with. # It knows which tables to drop because in the drop_all() command the connection to the sql database is made automatically (based on info in the db object) if cfg.drop_all_tables: print("Dropping all tables") db.drop_all() db.create_all() # Must be called after all classes are defined (otherwise it doesn't create the tables. connection_error = False # set connection error to false so we can continue except exc.SQLAlchemyError: counter += 1 print("Connection failed " + str(counter) + " time(s).") time.sleep(5) if connection_error: raise exc.SQLAlchemyError # connection failed, tried for 250 seconds. def register_blueprints(app): # Since the application instance is now created, register each Blueprint # with the Flask application instance (app) from project.home import home_blueprint from project.login import login_blueprint from project.topic import topic_blueprint from project.question import question_blueprint from project.answer import answer_blueprint app.register_blueprint(home_blueprint) app.register_blueprint(login_blueprint) app.register_blueprint(topic_blueprint) app.register_blueprint(question_blueprint) app.register_blueprint(answer_blueprint) def start_scheduler(): import project.scheduler #This will trigger the scheduler.__init__ file which will start the scheduler
终端输出内容
INFO [alembic.runtime.migration] Context impl MySQLImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.autogenerate.compare] Detected added table 'Topic' INFO [alembic.autogenerate.compare] Detected added table 'User' INFO [alembic.autogenerate.compare] Detected added table 'Question' INFO [alembic.autogenerate.compare] Detected added table 'TopicSubscription' INFO [alembic.autogenerate.compare] Detected added table 'Evaluation' INFO [alembic.autogenerate.compare] Detected added table 'QuestionSubscription' INFO [alembic.autogenerate.compare] Detected removed table 'question' INFO [alembic.autogenerate.compare] Detected removed table 'topicsubscription' INFO [alembic.autogenerate.compare] Detected removed table 'evaluation' INFO [alembic.autogenerate.compare] Detected removed index 'email' on 'user' INFO [alembic.autogenerate.compare] Detected removed index 'name' on 'user' INFO [alembic.autogenerate.compare] Detected removed index 'nickname' on 'user' INFO [alembic.autogenerate.compare] Detected removed index 'profile_pic' on 'user' INFO [alembic.autogenerate.compare] Detected removed table 'user' INFO [alembic.autogenerate.compare] Detected removed table 'topic' INFO [alembic.autogenerate.compare] Detected removed table 'questionsubscription'
已尝试的解决方法
- 试过相关Stack Overflow解决方案但无效,已将env.py还原为默认形式
请问哪里操作有误?
PS:不确定问题根源,仅分享了这些脚本,若需其他内容请告知。
内容的提问来源于stack exchange,提问作者ThaNoob
相关产品推荐
相关产品推荐

