Flask-无法使用其他文件中的Flask和Flask-mail实例 [英] Flask - cannot use Flask and Flask-mail instances from other files

查看:123
本文介绍了Flask-无法使用其他文件中的Flask和Flask-mail实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用Flask构建应用程序.我正在努力访问Flask实例"app"以及Flask-mail实例"mail".

I'm currently building an application with Flask. I'm struggling to access Flask instance 'app' as well as Flask-mail instance 'mail'.

下面是我的项目的样子:

Below is how my project looks like:

└── 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

烧瓶实例是使用create_app函数在run.py中创建的(来自

Flask instance is created in run.py with create_app function (from

import os

from application import create_app

config_name = os.getenv('FLASK_CONFIG')
app = create_app(config_name)

if __name__ == '__main__':
    app.run()

应用程序/__ 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

我要使用的是"app"和"mail".例如,在application/auth/token中:

What I want to do is to use 'app' and 'mail'. For example, in application/auth/token:

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中:

or in 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

I need both of these function in application/aut/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'))

我得到的是错误未定义全局名称应用"或未定义全局名称邮件".我尝试从应用程序导入应用程序导入变量,这会向我返回导入错误无法导入应用程序"

What I get is an error 'global name app is not defined' or 'global name mail is not defined'. I tried to import the variable with from application import app which return me an import error 'cannot import app'

感谢您的支持

推荐答案

由于使用的是应用程序工厂,因此需要像对Flask-SQLAlchemy类一样在Flask-Mail类上使用.init_app方法. from application import app将不起作用,因为在调用run.py

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

应用程序/__ 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而不是实例本身来引用应用程序实例. 此处是更深入的解释

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() 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

还应注意,除了views.py

编辑

旁注:您不必将用户添加到会话中,因为在路由的前面查询时已添加了该用户.我本人很长时间没有意识到这一点.

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_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'))

这篇关于Flask-无法使用其他文件中的Flask和Flask-mail实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆