Flask - cannot use Flask and Flask-mail instances from other files Flask - cannot use Flask and Flask-mail instances from other files flask flask

Flask - cannot use Flask and Flask-mail instances from other files


Since you are using an application factory you need to use the .init_app method on the Flask-Mail class like you did the Flask-SQLAlchemy class. from application import app will not work since you are never initializing an instance of the flask application until you call the create_app function in run.py

application/__init__.py

from flask_mail import Mailmail = Mail()def create_app(config_lvl):    # stuff    mail.init_app(app)    # more stuff    return app

Also you can use current_app to refer to the application instance instead of the instance itself as long as the block of code you use it in is being ran in a flask application. Here is a more in depth explanation.

application/auth/email.py

from application import mail  # you can now import the Mail() objectfrom flask_mail import Messagefrom flask import current_app  # use this to reference current application contextdef send_email(to, subject, template):    msg = Message(        subject,        recipients=[to],        html=template,        sender=current_app.config['MAIL_DEFAULT_SENDER']    )    mail.send(msg)

application/auth/token.py

from itsdangerous import URLSafeTimedSerializerfrom flask import current_appdef generate_confirmation_token(email):    serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])    return serializer.dumps(email, salt=current_app.config['SECURITY_PASSWORD_SALT'])def confirm_token(token, expiration = 600):    serializer = URLSafeTimedSerializer(current_app.config['SECRET_KEY'])    try:        email = serializer.loads(            token,            salt=current_app.config['SECURITY_PASSWORD_SALT'],            max_age=expiration        )    except:        return False    return email

also should note that you don't need from . import auth in any of your modules under the auth blueprint except views.py

EDIT

Side note: You don't have to add the user to the session because it was added when you queried for it earlier in the route. I was unaware of this for the longest time myself.

@auth.route('/confirm/<token>')@login_requireddef confirm_email(token):    try:        email = confirm_token(token)    except:        flash('The confirmation link is invalid or has expired.', 'danger')    user = User.query.filter_by(email=email).first_or_404()    if user.confirmed:        flash('Account already confirmed. Please login.', 'success')    else:        user.confirmed = True        user.confirmed_on = datetime.datetime.now()      #  db.session.add(user) # can remove this        db.session.commit()        flash("You've confirmed your account. Thanks!", 'success')    return redirect(url_for('auth.login'))


According to http://flask.pocoo.org/docs/0.12/patterns/appfactories/ you have to use current_app (from flask import current_app) to access your Flask instance for wherever in your application.Then you can use your config variables: current_app.config['DEBUG'] for instance.

Another point to consider when using application factories, create instance class instances outside of the 'create_app()' function. Then you have to use .init_app method:

Below is an example:

from flask_mail import Mailmail= Mail()def create_app():    mail.init_app(app)