0

Good day, I am new to Flask. In the midst of developing my "to do list" app, I wanted to modify detail of "email" column in databases.py.

Below is databases.py:

from flask_sqlalchemy import SQLAlchemy

# Create SQLAlchemy instance
db = SQLAlchemy()


# Define database models

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(10), unique=False, nullable=False)
    last_name = db.Column(db.String(10), unique=False, nullable=False)
    email = db.Column(db.String(20), unique=True, nullable=False)
    password = db.Column(db.String(12), nullable=True)

My app requires user to login with email and password hence I believe "email" should be unique. So I changed the unique parameter from False to True.

Based on Flask-Migrate documentation, I should execute commands flask db migrate -m "brief description" and flask db upgrade each time the database models change.

However, I encountered error message RuntimeError: A 'SQLAlchemy' instance has already been registered on this Flask app. Import and use that instance instead. when I execute commands flask --debug run / flask db migrate.

Below is app.py:

from flask import Flask, render_template, request, redirect, url_for, flash, get_flashed_messages, session
from email_validator import validate_email, EmailNotValidError
import secrets
from flask_bootstrap import Bootstrap5
from flask_migrate import Migrate
from flask_session import Session

# Create instance for Bootstrap 5
bootstrap = Bootstrap5()

# Create session instance
user_session = Session()

def create_app():
    app = Flask(__name__)

    # Set database location
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///notes.db'

    # configure user session
    app.config['SESSION_TYPE'] = 'sqlalchemy'
    app.config['SESSION_PERMANENT'] = False
    user_session.init_app(app)

    from databases import db, User

    db.init_app(app)

    with app.app_context():
        db.create_all()

    # Database migration
    '''
    Required actions:
    
    1. execute command in terminal for very first time => Flask --debug run
    2. execute command in terminal => flask db init
    3. execute command in terminal => flask db migrate -m "Initial migration"
    4. execute command in terminal => flask db upgrade
    '''
    migrate = Migrate(app, db)
    
    # Flask-WTF
    app.secret_key = secrets.token_hex(8)

    # initiate Bootstrap5 for the app
    bootstrap.init_app(app)

    from forms import new_user, login_user

    @app.route('/register', methods=['GET', 'POST'])
    def register():

        register_user = new_user()

        if register_user.validate_on_submit():

            profile = User(
                first_name = request.form.get('first_name'),
                last_name = request.form.get('last_name'),
                email = request.form.get('email'),
                password = request.form.get('password')
            )

            db.session.add(profile)
            db.session.commit()

            return  redirect(url_for('login'))

        return  render_template('new_user.html', form=register_user)

    @app.route('/')
    @app.route('/login', methods=['GET', 'POST'])
    def login():

        user_login = login_user()

        if user_login.validate_on_submit():

            invalid_email = None
            invalid_password = None
            email_input = request.form.get('email')
            password_input = request.form.get('password')
            checkbox = request.form.get('checkbox')

            user_record = db.session().execute(
                db.select(User).filter_by(email=email_input)
            ).scalar_one_or_none()

            if not user_record:
                invalid_email = f"Invalid email !!"
                return render_template('login.html', form=user_login, invalid_email=invalid_email)
            elif user_record.password != password_input:
                invalid_password = f"Wrong password !!"
                return render_template('login.html', form=user_login, invalid_password=invalid_password)
            else:
                user_session['email'] = email_input if checkbox else None
                return  redirect(url_for('profile', id=user_record.id))

        return  render_template('login.html', form=user_login)
    
    @app.route('/profile/<int:id>')
    def profile(id):

        if user_session.get('email'):
            
            user_record = db.session().execute(
                    db.select(User).filter_by(id=id)
                ).scalar_one_or_none()

            flash(message=f"Welcome back, { user_record.first_name }", category='info')

            return  render_template('user_homepage.html', user=user_record)
        
        return redirect(url_for('login'))

    return app

Appreciete if anyone can point out my mistake.

3
  • This question is similar to: RuntimeError: A 'SQLAlchemy' instance has already been registered on this Flask app. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Dec 20, 2024 at 0:45
  • Hi @ewokx, thanks for quick response. actually, the flask db init, flask db migrate and flask db upgrade work at first. flask --debug run / flask db migrate failed after make the changes. I am not sure which part is wrong and what is the difference between my issue with the answer you recommended. Commented Dec 20, 2024 at 1:14
  • First of all, remove the db.create_all() call. Second, please include the complete exception message and stack trace that you receive. Commented Dec 21, 2024 at 8:38

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.