首页 > 解决方案 > 当用户输入数据太慢时发送电子邮件的功能,flask sqlalchemy

问题描述

大家好,我做了一个功能,当用户 14 天没有输入数据时,它会发送一封电子邮件,不幸的是,当它执行时它可以工作,但速度很慢。我会喜欢一些关于如何让它更快的提示。而且写得更好

功能

def enviar_email_checkup():
users= [1,2]
for user in users:
    ultimadata=db.session.query(Dado.DataDeInsercao).filter_by(user_id = user).order_by(Dado.DataDeInsercao.desc()).limit(1).scalar()
    dueduser=db.session.query(UsuarioDB.EmailDB,UsuarioDB.id).filter_by(id = user).order_by(UsuarioDB.id.desc()).limit(1).scalar()
    datahoje=datetime.datetime.utcnow()
    diff= datahoje-ultimadata
    if diff.days >= 14:
        msg = Message('Falta de dados',sender='ivgnoreply@gmail.com', recipients= [dueduser])
        msg.body =   'Isso e um email para vc parar de ser vagabundo'
        mail.send(msg)
    else:
        break

执行时的路由

@Principal.route("/HomePage", methods=['GET', 'POST'])
def HomePage():
     enviar_email_checkup()
     return render_template("HomePage.html",title = "HomePage")

标签: pythonflaskflask-sqlalchemy

解决方案


在循环中进行数据库查询是非常低效的。通常最好构建一个一次性获取所有所需数据的查询。

似乎您想要做的是识别Dado在某个日期之后在表上没有条目的所有用户。我们可以通过创建带有NOT EXISTS子句的查询来做到这一点。

# This example uses pure-sqlalchemy, but converting to flask-sqlalchemy should not be 
# too difficult, for example 
# session.query(UsuarioDB).filter(...) -> UsuarioDB.query.filter(...)

from sqlalchemy.sql import exists

diff_date = datetime.date.today() - datetime.timedelta(14)

stmt = exists().where(sa.and_(
                          Dado.DataDeInsercao >= diff_date,
                          UsuarioDB.id == Dado.user_id))

# The '~' here is a negation operator
q = session.query(UsuarioDB).filter(~stmt)

for usuario in q:
    # send message

该查询生成以下 SQL:

SELECT usuario.id AS usuario_id, usuario."EmailDB" AS "usuario_EmailDB" 
FROM usuario 
WHERE NOT (EXISTS (SELECT * 
FROM dado 
WHERE dado."DataDeInsercao" >= ? AND usuario.id = dado.user_id))

如果您在模型之间创建了关系,请这样说:

from sqlalchemy import orm

class UsuarioDB(Base):
    ...
    dados = orm.relationship('Dado')

然后我们可以稍微简化一下 Python 代码(生成相同的 SQL):


q = session.query(UsuarioDB).filter(~UsuarioDB.dados.any(Dado.DataDeInsercao >= diff_date))

for usuario in q:
    # send message

如果在每次迭代中都创建与服务器的新连接,则循环发送电子邮件也可能很耗时。是否有批量发送选项可能值得检查。


推荐阅读