简体   繁体   English

有没有更pythonic/更有效的方法来编写这段代码

[英]Is there a more pythonic/efficient way to write this code

if request.method == "POST":
    user = None
    users = User.query.all()
    for x in users:
        if x.email == request.form["email"] and check_password_hash(x.password, request.form["password"]):
            user = x
    if not user:
        return render_template("login.html",err = "Invalid Credentials")
    else:
        login_user(user)
        return redirect(url_for("home"))
else:
    if current_user.is_authenticated:
        return redirect(url_for("home"))

I'm always finding myself setting a variable = None then later checking if the variable is still None like the example above.我总是发现自己设置了一个变量 = None 然后稍后检查变量是否仍然像上面的例子一样 None 。 I feel like there are way better ways to write this but I can't think of any.我觉得有更好的方法来写这个,但我想不出任何方法。 Any help is appreciated任何帮助表示赞赏

Instead of querying the database for all users and then looping through all the results in your application, let the database do the work.不是为所有用户查询数据库,然后遍历应用程序中的所有结果,而是让数据库完成工作。

Here's how I'd rewrite your code snippet (I'm guessing you're using Flask-SQLAlchemy):以下是我如何重写您的代码片段(我猜您正在使用 Flask-SQLAlchemy):

if request.method == "POST":
    user = User.query.filter_by(email=request.form["email"]).first()
    if not user or not check_password_hash(user.password, request.form["password"]):
        return render_template("login.html", err="Invalid Credentials")
    login_user(user)
    return redirect(url_for("home"))

if current_user.is_authenticated:
    return redirect(url_for("home"))

Some things to note:一些注意事项:

  • simplify your flow control and avoid unnecessary nesting简化流程控制并避免不必要的嵌套
  • in your code, you're looping through all users in the database, even after you've found the user in question.在您的代码中,您正在遍历数据库中的所有用户,即使在您找到相关用户之后也是如此。 Make sure to use break and continue statements to avoid unnecessary work确保使用breakcontinue语句以避免不必要的工作
  • avoid manually implementing logic for tasks that databases are built for (eg querying and filtering data)避免为构建数据库的任务手动实现逻辑(例如查询和过滤数据)

You could use a try/except and catch a NameError .您可以使用try/except并捕获NameError

try:
    login_user(user)
    return redirect(url_for("home"))
except NameError:
    render_template("login.html",err = "Invalid Credentials")

This does not require you to define user=None , and makes more sense in terms of readability, assuming you expect to get a user more often than not.这不需要您定义user=None ,并且在可读性方面更有意义,假设您希望更频繁地获得用户。 I am a little confused by your code, however, because you are iterating through a list but only assigning one variable.但是,我对您的代码有点困惑,因为您正在遍历列表但只分配一个变量。 Why not put all of the code in the loop under the if statement?为什么不将所有代码都放在if语句下的循环中? I am sure you have a reason to not do that, but it is not clear from your code.我相信你有理由不这样做,但你的代码并不清楚。

I find the code in the question is good enough and the logic is clear.我发现问题中的代码足够好并且逻辑清晰。

That said, below is an example using list comprehension to show another approach.也就是说,下面是一个使用列表理解来展示另一种方法的例子。 Note that there won't be efficiency gain.请注意,不会提高效率。 It is a matter of preference and style.这是一个偏好和风格的问题。

if request.method == "POST":
    def _validated(x):
        return (x.email == request.form["email"] and
                check_password_hash(x.password, request.form["password"])

    users = [x for x in User.query.all() if _validated(x)]
    if len(users) == 0:
        return render_template("login.html",err = "Invalid Credentials")
    else:
        login_user(users[0])
        return redirect(url_for("home"))
else:
    if current_user.is_authenticated:
        return redirect(url_for("home"))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM