I have a simple conceptual question about the Flask application factory pattern.
I'm trying to use Flask-Mail across different files. My __init__.py file is:
#
# __init__.py
#
from flask import Flask
from flask_pymongo import PyMongo
from flask_mail import Mail
from flask_login import LoginManager
mail = Mail()
mongo = PyMongo()
login_manager = LoginManager()
def create_app():
app = Flask(__name__, instance_relative_config=False)
app.config.from_object('config.DevConfig')
mail.init_app(app)
login_manager.init_app(app)
mongo.init_app(app, retryWrites = False)
with app.app_context():
from .views import bp
app.register_blueprint(views.bp)
return app
And the other file:
#
# views.py
#
from flask import Blueprint
from flask import current_app as app
from flask_mail import Message
from app import mongo, mail, login_manager
bp = Blueprint('bp', __name__, template_folder='templates', static_folder='static')
@bp.route('/')
def index():
msg = Message("Success", recipients=[ email ])
with open('template.html', 'r') as fd:
msg.html = fd.read()
mail.send(msg)
Though I set MAIL_DEFAULT_SENDER in my config file, I'm getting the error that there is no default sender specified when hitting the mail.send(msg) line in views.py. After checking the mail object, I saw that it had no config variables set.
Per this tutorial, it seemed that I'd need to manually set current_app.config['MAIL_DEFAULT_SENDER'] whenever using the mail object under this pattern, and would need to write an additional with app.app_context(): block around the mail object such that it was instantiated with the proper config variables.
This seems like a lot of extra work, so is there another way to directly get the mail object that was initialized in create_app with all the proper config variables set?
Appreciate the help with this!
EDIT:
Created extensions.py:
from flask_pymongo import PyMongo
from flask_mail import Mail
from flask_login import LoginManager
mail = Mail()
mongo = PyMongo()
login_manager = LoginManager()
And modified __init__.py to be:
from flask import Flask
def create_app():
app = Flask(__name__, instance_relative_config=False)
app.config.from_object('config.DevConfig')
from app.extensions import mail, login_manager, mongo
mail.init_app(app)
login_manager.init_app(app)
mongo.init_app(app, retryWrites = False)
with app.app_context():
from .views import bp
app.register_blueprint(views.bp)
return app
And for views.py, I have:
from flask import Blueprint
from flask import current_app
from flask_mail import Message
from app.extensions import mongo, mail, login_manager
bp = Blueprint('bp', __name__, template_folder='templates', static_folder='static')
@bp.route('/')
def index():
msg = Message("Success", recipients=[ email ])
with open('template.html', 'r') as fd:
msg.html = fd.read()
mail.send(msg)