1
\$\begingroup\$

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")
asked May 28, 2021 at 22:43
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

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.

Mast
13.8k12 gold badges56 silver badges127 bronze badges
answered May 28, 2021 at 22:56
\$\endgroup\$
1
  • \$\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\$ Commented May 28, 2021 at 23:28
1
\$\begingroup\$

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 }}
answered May 30, 2021 at 19:25
\$\endgroup\$
1
  • \$\begingroup\$ I'm using flask_session for login and cs50 for SQL, I don't know how I could implement this. \$\endgroup\$ Commented May 31, 2021 at 23:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.