Чтобы бросить свою причину и решение в кольцо, я использую flask
и flask-sqlalchemy
, чтобы управлять всеми своими сессиями.Это нормально, когда я делаю что-то через сайт, но когда я делаю что-то через командную строку и скрипты, вы должны убедиться, что все, что делает флеш-у, связано с контекстом фляги.Итак, в моей ситуации мне нужно было получить вещи из базы данных (используя flask-sqlalchemy
), затем отобразить их в шаблоны (используя render_template колбы), а затем отправить их по электронной почте (используя flask-mail
).то, что я сделал, было что-то вроде
def render_obj(db_obj):
with app.app_context():
return render_template('template_for_my_db_obj.html', db_obj=db_obj
def get_renders():
my_db_objs = MyDbObj.query.all()
renders = []
for day, _db_objs in itertools.groupby(my_db_objs, MyDbObj.get_date):
renders.extend(list(map(render_obj, _db_obj)))
return renders
def email_report():
renders = get_renders()
report = '\n'.join(renders)
with app.app_context():
mail.send(Message('Subject', ['me@me.com'], html=report))
(это в основном псевдокод, я делал другие вещи в разделе группировки)
И когда я бегал, ясначала пройдите _db_obj
, но потом я получу ошибку при любом запуске после.
Виновник?with app.app_context()
.
Обычно, когда вы выходите из этого контекста , он делает несколько вещей, в том числе как-то освежает соединения db.Одна из вещей, которая вытекает из этого, это избавление от последнего сеанса, который был вокруг, который был сеансом, с которым были связаны все my_db_objs
.
Есть несколько различных вариантов решений, но я пошелс вариантом,
def render_obj(db_obj):
return render_template('template_for_my_db_obj.html', db_obj=db_obj
def get_renders():
my_db_objs = MyDbObj.query.all()
renders = []
for day, _db_objs in itertools.groupby(my_db_objs, MyDbObj.get_date):
renders.extend(list(map(render_obj, _db_obj)))
return renders
def email_report():
with app.app_context():
renders = get_renders()
report = '\n'.join(renders)
mail.send(Message('Subject', ['me@me.com'], html=report))
Только 1 with app.app_context()
, который охватывает их все.Главное, что вам нужно сделать (если у вас есть настройки, подобные моей), это убедиться, что любой используемый вами объект дБ находится «внутри» любого используемого вами app_context.Если вы сделаете то, что я сделал в первой итерации, все ваши объекты в дБ потеряют свою сессию, оканчивающуюся на DetachedInstanceError
, как я.