I'm using Flask on Python and I'm displaying the username at the top of the site (and it's working) as follows:
@app.route("/")
@login_required
def index():
"""Queries the user's First Name to display in the title"""
names = db.execute("""
SELECT first_name
FROM users
WHERE id=:user_id
""",
user_id = session["user_id"]
)
return render_template("index.html", names = names)
<header class="mainHeader">
{% for name in names %}
<h1>{{ name["first_name"] }}' Bookshelf</h1>
{% else %}
<h1>Your Bookshelf</h1>
{% endfor %}
</header>
I don't know if it is necessary, but here is my database configuration:
TABLE: users -- id: integer, email: text, first_name: text, last_name: text, picture: text
Although it is working, I believe that it is not ideal to use for loop to display just one name. Does anyone have any suggestions?
Editing to include login routine:
@app.route("/login", methods=["GET", "POST"])
def login():
"""Log user in"""
# Forget any user_id
session.clear()
# User reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# Ensure email and password was submitted
result_checks = is_provided("email") or is_provided("password")
if result_checks is not None:
return result_checks
# Query database for email
rows = db.execute("SELECT * FROM users WHERE email = ?", request.form.get("email"))
# Ensure email exists and password is correct
if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
return "E-mail ou Senha inválidos"
# Remember which user has logged in
session["user_id"] = rows[0]["id"]
session["email"] = request.form.get("email")
# Redirect user to home page
return redirect("/")
# User reached route via GET (as by clicking a link or via redirect)
else:
return render_template("login.html")
2 Answers 2
according to the query, it seems that the row count is either 0 or 1. so the loop would either have no iterations (the else
part) or have exactly one iteration.
in terms of performance, I think that any improvement here is not dramatic.
however, in terms of choosing the right coding tools for the job, it seems that a loop is not the right tool.
maybe the following would be better:
@app.route("/")
@login_required
def index():
"""Queries the user's First Name to display in the title"""
names = db.execute("""
SELECT first_name
FROM users
WHERE id=:user_id
""",
user_id = session["user_id"]
)
first_name = names[0]["first_name"] if names else None
return render_template("index.html", first_name = first_name)
and then:
<header class="mainHeader">
{% if first_name %}
<h1>{{ first_name }}'s Bookshelf</h1>
{% else %}
<h1>Your Bookshelf</h1>
{% endif %}
</header>
note: I didn't test the code.
-
\$\begingroup\$ It is working fine! I really appreciate! The
else
was there because I was trying to implement an if statement and then I forgot to remove before inserting the code here. Thanks @Ron! \$\endgroup\$ARNON– ARNON2021年05月28日 23:28:44 +00:00Commented May 28, 2021 at 23:28
To be honest, this is a case where you are expecting exactly one record (right ?), given that there must be a valid session for a logged-in user. So, if anything else happens (no record or worse, more than one record) I would trigger an exception. Either there is a problem with your database or your programming logic. If I'm not wrong, this is a not a page that allows anonymous access anyway.
I assume that you use Flask-Login. Personally I use a custom User class like this, but with Flask SQL Alchemy as the ORM:
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
# add more ...
So when the login is made some additional fields are already populated from the DB as per the data model. You just have to display them. These are session variables, so they don't have to be reloaded every time. They just have to be refreshed if they change. Your query should not hurt a lot in terms of performance but it is still slightly wasteful.
The login routine is something like this:
@cp_bp.route('/login', methods=['GET', 'POST'])
def login():
errors = []
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
errors.append('Invalid username or password')
# log failure
# return redirect(url_for('login'))
else:
login_user(user)
And then in my templates I can use tags like:
{{ current_user.username }}
-
\$\begingroup\$ I'm using
flask_session
for login andcs50
for SQL, I don't know how I could implement this. \$\endgroup\$ARNON– ARNON2021年05月31日 23:03:23 +00:00Commented May 31, 2021 at 23:03