Во время многопоточности Flask появляется ошибка с использованием app_context, но это не работает - PullRequest
0 голосов
/ 17 июня 2020

Я создал маршрут для проверки отправки электронного письма. При посещении / book_blast я получаю сообщение об ошибке выполнения. Я по-разному пытался добавить app_context (), но ни один из них не устранил ошибку. Если я удалю отправку писем, все заработает. Если я удалю многопоточную отправку писем и отправлю их в обычном режиме, все заработает.

@books.route("/book_blast")

def book_blast ():

all_free_books = Book.query.all()

# pass in: username, books, token
subscribers = Mail_Subscription.query.filter(Mail_Subscription.daily_promotions == True).all()

# send emails one-by-one based on user preferences
for subscriber in subscribers:
    user = subscriber.user
    email = subscriber.email
    name = 'Subscriber'
    if user:  # if there is a connected user and not just an email subscriber
        name = user.first_name + " " + user.last_name if user.first_name and user.last_name else user.username

    token_url = url_for('books.email_preferences') + "/" + get_unsubscribe_token_for_email_list(email)
    books = [book for book in all_free_books if
             book.stars >= subscriber.rating and book.reviews >= subscriber.reviews and book.genre in subscriber.genres.split(
                 ',')]
    print(f'{name} ({email}) will receive: {books}')

    html = render_template('book_blast.html', name=name, token_url=token_url, books=books)
    msg = Message(f'Free Books {datetime.datetime.now().date()}',
                  sender=current_app.config['MAIL_DEFAULT_SENDER'],
                  recipients=[email])

    msg.body = f'We have {len(books)} for free today. Visit {url_for("books.email_preferences")} to read more.'
    msg.html = html

    # send emails

    """
    app = current_app
    with app.app_context():
    """

    app = current_app
    app.app_context()

    with concurrent.futures.ThreadPoolExecutor() as executor:
        future = executor.submit(mail.send, msg)
        future.result()

return html

1 Ответ

0 голосов
/ 17 июня 2020

Я предлагаю вам создать что-то вроде send_email.py, которое выглядит примерно так.

 from flask import current_app, render_template
 from flask_mail import Message
 from threading import Thread
 from . import mail


def send_async_mail(app, msg):
    with app.app_context():
         mail.send(msg)

def send_email(to, subject, template, **kwargs):
     app = current_app._get_current_object()
     msg = Message(app.config['MAIL_SUBJECT_PREFIX'] + subject,
     sender=app.config['MAIL_SENDER'], recipients=[to])
     msg.body = render_template(template + '.txt', **kwargs)
     msg.html = render_template(template + '.html', **kwargs)
     thr = Thread(target=send_async_mail, args=[app, msg])
     thr.start()
     return thr

После этого внутри вашего представления просто импортируйте функцию send_mail

   send_email(TO, 'TITLE!','template/location') 

Также я был используя flask почту и здесь ... надеюсь, это вам немного поможет.

...