我目前正在使用 Flask 构建一个应用程序。我正在努力访问 Flask 实例“app”以及 Flask-mail 实例“mail”。
下面是我的项目的样子:
└── my-project
├── application
│ ├── __init__.py
│ ├── admin
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ └── views.py
│ ├── auth
│ │ ├── __init__.py
│ │ ├── forms.py
│ │ └── views.py
│ │ └── token.py
│ │ └── email.py
│ ├── home
│ │ ├── __init__.py
│ │ └── views.py
│ ├── models.py
│ ├── static
│ └── templates
│ └──....
│
├── config.py
├── instance
│ └── config.py
├── migrations
│ ├── README
│ ├── alembic.ini
│ ├── env.py
│ ├── script.py.mako
│ └── versions
│ └── a1a1d8b30202_.py
├── requirements.txt
└── run.py
Flask 实例是在 run.py 中使用 create_app 函数创建的(来自
运行.py
import os
from application import create_app
config_name = os.getenv('FLASK_CONFIG')
app = create_app(config_name)
if __name__ == '__main__':
app.run()
application/__init__.py
# third-party imports
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_bootstrap import Bootstrap
from flask_mail import Mail
import stripe
# local imports
from config import app_config
# db variable initialization
db = SQLAlchemy()
login_manager = LoginManager()
LoginManager.user_loader
def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config[config_name])
app.config.from_pyfile('config.py')
Bootstrap(app)
db.init_app(app)
login_manager.init_app(app)
mail = Mail(app)
migrate = Migrate(app,db)
from application import models
from .admin import admin as admin_blueprint
app.register_blueprint(admin_blueprint, url_prefix='/admin')
#the rest of the blueprint import goes here
return app
我想做的是使用“应用程序”和“邮件”。例如,在 application/auth/token 中:
application/auth/token.py
from itsdangerous import URLSafeTimedSerializer
from . import auth
def generate_confirmation_token(email):
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
return serializer.dumps(email, salt=app.config['SECURITY_PASSWORD_SALT'])
def confirm_token(token, expiration = 600):
serializer = URLSafeTimedSerializer(app.config['SECRET_KEY'])
try:
email = serializer.loads(
token,
salt=app.config['SECURITY_PASSWORD_SALT'],
max_age=expiration
)
except:
return False
return email
或在 application/auth/email.py 中:
application/auth/email.py
from flask_mail import Message
from . import auth
def send_mail(to, subject, template):
msg = Message(
subject,
recipients=[to],
html=template,
sender=app.config['MAIL_DEFAULT_SENDER']
)
mail.send(msg)
我需要 application/aut/views.py 中的这两个函数
application/auth/views.py
from flask import flash, redirect, render_template, url_for, request
from flask_login import login_required, login_user, logout_user
from werkzeug.security import check_password_hash
import datetime
from . import auth
from forms import LoginForm, RegistrationForm
from .. import db
from ..models import User
@auth.route('/register', methods=['GET', 'POST'])
def register():
"""
Handle requests to the /register route
Add a user to the database through the registration form
"""
form = RegistrationForm()
form.id = 'form_signup'
if form.validate_on_submit():
user = User(email=form.email.data,
#username=form.username.data,
first_name=form.first_name.data,
last_name=form.last_name.data,
password=form.password.data,
registered_on=datetime.datetime.now(),
confirmed=False,
premium=False)
# add employee to the database
db.session.add(user)
db.session.commit()
flash("We've just sent you an email confirmation. Please activate you account to completly finish your registration", 'succes')
token = generate_confirmation_token(user.email)
confirm_url = url_for('auth.confirm_email', token=token, _external=True)
html = render_template('auth/activate.html', confirm_url=confirm_url)
subject = "Please confirm your email"
send_email(user.email, subject, html)
login_user(user)
flash('A confirmation email has been sent via email.', 'success')
# redirect to the login page
#return redirect(url_for('auth.login'))
return redirect(url_for('home.homepage'))
# load registration template
return render_template('auth/register.html', form=form, title='Register')
@auth.route('/confirm/<token>')
@login_required
def 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.', 'succes')
else:
user.confirmed =True
user.confirmed_on = datetime.datetime.now()
db.session.add(user)
db.session.commit()
flash("You've confirmed your account. Thanks!", 'succes')
return redirect(url_for('auth.login'))
我得到的是错误“全局名称应用程序未定义”或“全局名称邮件未定义”。我尝试使用 from application import app 导入变量,这给我返回导入错误“无法导入应用程序”
感谢您的支持
最佳答案
由于您使用的是应用程序工厂,因此您需要使用 .init_app
Flask-Mail
上的方法像你那样上课 Flask-SQLAlchemy
类(class)。 from application import app
将不起作用,因为在调用 create_app
之前,您永远不会初始化 Flask 应用程序的实例。函数位于 run.py
application/__init__.py
from flask_mail import Mail
mail = Mail()
def create_app(config_lvl):
# stuff
mail.init_app(app)
# more stuff
return app
您也可以使用current_app
只要您使用它的代码块正在 Flask 应用程序中运行,就可以引用应用程序实例而不是实例本身。 Here是更深入的解释。
application/auth/email.py
from application import mail # you can now import the Mail() object
from flask_mail import Message
from flask import current_app # use this to reference current application context
def 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 URLSafeTimedSerializer
from flask import current_app
def 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
还应该注意,您不需要 from . import auth
在 auth
下的任何模块中蓝图除外views.py
编辑
旁注:您不必将用户添加到 session 中,因为它是在您之前在路由中查询时添加的。我自己很长一段时间都没有意识到这一点。
@auth.route('/confirm/<token>')
@login_required
def 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'))
关于python - Flask - 无法使用其他文件中的 Flask 和 Flask-mail 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45026990/