Search code examples
pythonroutesflaskwerkzeug

Route two modules to the same URL in Flask by session


I have a not-logged-in module/blueprint, welcome, and a logged-in blueprint, home. I want a user with a valid session to go to home.index, and a user that is a guest to go to welcome.index. However, I am running into issues because both of those functions route to the same URL, /.

How can I make this functionality possible? I have tried adding:

if(logged_in():
    redirect(url_for('home.index'))

to index() in the welcome blueprint, but this of course just causes a circular redirect, because the URL for home.index is the same as welcome.index.

I have also tried to only define welcome.index if logged_in() is true. However, that causes issues because there are other links on the site that link to welcome.index, and if the user is logged in, those cause errors as welcome.index technically no longer exists.

Edit

I am seeing this error AttributeError: 'Blueprint' object has no attribute 'index' from this code:

from flask import Flask, session, g

from modules.welcome import welcome
from modules.home import home as home

from modules.home import index
from modules.welcome import index

 app = Flask(__name__)
 app.config.from_pyfile('config.cfg')

 app.register_blueprint(welcome)
 app.register_blueprint(home)

 @app.route('/', methods=['GET', 'POST'])
 def index():
    if 'user_id' in session:
        return home.index()
    else:
        return welcome.index()

Edit #2: Blueprints code

Code in modules/home.py:

from flask import Blueprint, render_template, redirect, url_for, request, session, g

from models.User import User
from helpers.login import *

home = Blueprint('home', __name__)

def index():
    return render_template('home/index.html')

Code in modules/welcome.py:

from flask import Blueprint, render_template, redirect, url_for, request, session, g
import md5

from models.User import User
from helpers.login import *

welcome = Blueprint('welcome', __name__)

def index():
    alert, email = None, None
    if request.method == 'POST' and not logged_in():
        email = request.form['email'] 
        password_salt = md5.new(request.form['password']).hexdigest()
        user = User.query.filter_by(email=email , password_salt=password_salt).first()
        if user is None:
            alert = "Wrong username or password!"
        else:
            session['user_id'] = user.id
            return redirect(url_for('home.index'))
    return render_template('welcome/index.html', alert=alert, email=email)

@welcome.route('/about')
def about():
    return render_template('welcome/about.html')

@welcome.route('/tandp')
def tandp():
    return render_template('welcome/tandp.html')

@welcome.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect(url_for('welcome.index'))

@welcome.route('/register')
def register():
    error = None
    return "HI"

Solution

  • Split up your methods, test for logged status and then call the proper function (adding the params you need on each):

    from ????? import app
    from ????? import logged_in
    import home.index
    import welcome.index
    
    @app.route('/')
    def your_basic_index_view():
       if logged_in():
           return home.index()
       else:
           return welcome.index()
    

    Or do the same with a decorator. You won't be able to use a single route pointing conditionally to two different views.

    EDIT:

    Try the following:

    from flask import Flask, session, g
    
    from modules.welcome import welcome
    from modules.home import home as home
    
    from modules.home import index as h_index
    from modules.welcome import index as w_index
    
    app = Flask(__name__)
    app.config.from_pyfile('config.cfg')
    
    app.register_blueprint(welcome)
    app.register_blueprint(home)
    
    @app.route('/', methods=['GET', 'POST'])
    def index():
        if 'user_id' in session:
            return h_index()
        else:
            return w_index()