Home > Net >  I cannot solve this error: jinja2.exceptions.UndefinedError: 'user' is undefined
I cannot solve this error: jinja2.exceptions.UndefinedError: 'user' is undefined

Time:06-25

I'm a beginner to python and html (hence the messy code), and I've been taking bits from various tutorials, and piecing them together. I'm trying to create a web page that someone can make an account on, edit said account, and also login to said account, which will take them to the home page. I've gotten the edit page to work, but the other pages throw this error: jinja2.exceptions.UndefinedError: 'user' is undefined. I think I've passed the user variable to all the templates necessary, so I don't understand why I get this error.

here's my code:

main.py

from flask import Flask, render_template, url_for, request, flash, redirect, abort
import sqlite3
app = Flask(__name__)

def get_db_connection():
    conn = sqlite3.connect('database.db')
    conn.row_factory = sqlite3.Row
    return conn

def get_user(user_id):
    conn = get_db_connection()
    user = conn.execute('SELECT * FROM users WHERE id = ?',(user_id,)).fetchone()
    conn.close()
    if user is None:
        abort(404)
    return user

app.config['SECRET_KEY'] = '013ecbdd4aae3899c7feed1bf36dee4e'

@app.route("/home")
def home():
    conn = get_db_connection()
    user = conn.execute('SELECT * FROM users').fetchall()
    conn.close()
    return render_template('home.html', user=user)

@app.route("/")
@app.route("/about")
def about():
    return render_template('about.html')

@app.route("/register", methods=('GET', 'POST'))
def register():
    if request.method == 'POST':
        username = request.form['username']
        password1 = request.form['password1']
        password2 = request.form['password2']
        if not username:
            flash('Username is required!')
        elif not password1:
            flash('Password is required!')
        elif not password2:
            flash('Valdiated password is required!')
        elif password1 != password2:
            flash('Passwords do not match!')
        else:
            conn = get_db_connection()
            conn.execute('INSERT INTO users (username, password1) VALUES (?, ?)',(username, password1))
            conn.commit()
            conn.close()
            return redirect(url_for('home'))
    return render_template('register.html', title = 'Register')

@app.route("/login")
def login():
    return render_template('login.html', title = 'Login')

@app.route("/<int:id>/edit", methods=('GET', 'POST'))
def edit(id):
    user = get_user(id)
    if request.method == 'POST':
        username = request.form['username']
        password1 = request.form['password1']
        password2 = request.form['password2']
        if not username:
            flash('Username is required!')
        elif not password1:
            flash('Password is required!')
        elif not password2:
            flash('Valdiated password is required!')
        elif password1 != password2:
            flash('Passwords do not match!')
        else:
            conn = get_db_connection()
            conn.execute('UPDATE users SET username = ?, password1 = ?'
                         ' WHERE id = ?',
                         (username, password1, id))
            conn.commit()
            conn.close()
            return redirect(url_for('home'))

    return render_template('edit.html', user=user)

if __name__ == '__main__':
    app.run(debug=True)

layout.html

<html>
<head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA 058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
 
     <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles/main.css') }}">
<title>
    {% block title %} {% endblock %} - FlaskApp</title>
</title>
</head>
<body>
<div id="wrapBanner"> 
<img src="/static/test-photo1.jpg" alt="image not available" id="logo"/>
<div id="topBanner">
    <h2><b>title of web page</b></h2>
    <h4><b>subtitle</b></h4>
</div>
</div>
<div id="navBanner">
    <h3> 
    <a  href="{{ url_for('login') }}">Login</a>
    <a  href="{{ url_for('register') }}">Register</a>
    <a  href="{{ url_for('edit', id=user['id']) }}">Edit Account</a>
    </h3>
</div>
<div id="mainBanner">
    {% for message in get_flashed_messages() %}
            <div >{{ message }}</div>
        {% endfor %}
    {% block content %} {% endblock %}
</div>
<div id="footerBanner">
    <h4> 
    footer 
    </h4>
</div>
</body>
</html> 

edit.html

{% extends "layout.html" %}
{% block content%}
    <h1>{% block title %} Edit Account "{{ user['username'] }}" {% endblock %}</h1>
    <form method="post">
        <label for="username">New Username</label>
        <br>
        <input type="text" name="username"
            placeholder="Username"
            value="{{ request.form['username'] or user['username'] }}"></input>
        <br>
        
        <label for="password1"> New Password</label>
        <br>
        <input type="text" name="password1"
            placeholder="Password"
            value="{{ request.form['password1'] or user['password1'] }}"></input>
        <br>

        <label for="password2">Validate Password</label>
        <br>
        <input type="text" name="password2"
            placeholder="Validate Password"
            value="{{ request.form['password2'] or user['password1'] }}"></input>
        <br>
        <br>

        <button  type="submit">Submit</button>
    </form>
{% endblock content %}

register.html

{% extends "layout.html" %}
{% block content%}
    <h1>{% block title %} Make an account {% endblock %}</h1>
    <form method="post">
        <label for="username">Username</label>
        <br>
        <input type="text" name="username"
            placeholder="Username"
            value="{{ request.form['username'] }}"></input>
        <br>
        
        <label for="password1">Password</label>
        <br>
        <input type="text" name="password1"
            placeholder="Password"
            value="{{ request.form['password1'] }}"></input>
        <br>

        <label for="password2">Validate Password</label>
        <br>
        <input type="text" name="password2"
            placeholder="Validate Password"
            value="{{ request.form['password2'] }}"></input>
        <br>
        <br>

        <button  type="submit">Submit</button>
    </form>
{% endblock content %}

traceback:

Traceback (most recent call last):
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 2095, in __call__
    return self.wsgi_app(environ, start_response)
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 2080, in wsgi_app
    response = self.handle_exception(e)
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 2077, in wsgi_app
    response = self.full_dispatch_request()
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 1525, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 1523, in full_dispatch_request
    rv = self.dispatch_request()
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\app.py", line 1509, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "C:\Users\EzraLamdin\projectRoster\roster.py", line 30, in about
    return render_template('about.html')
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\templating.py", line 148, in render_template
    return _render(
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\flask\templating.py", line 128, in _render
    rv = template.render(context)
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\jinja2\environment.py", line 1301, in render
    self.environment.handle_exception()
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\jinja2\environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "C:\Users\EzraLamdin\projectRoster\templates\about.html", line 1, in top-level template code
    {% extends "layout.html" %}
  File "C:\Users\EzraLamdin\projectRoster\templates\layout.html", line 25, in top-level template code
    <a  href="{{ url_for('edit', id=user['id']) }}">Edit Account</a>
  File "c:\Users\EzraLamdin\projectRoster\.venv\lib\site-packages\jinja2\environment.py", line 466, in getitem
    return obj[argument]
jinja2.exceptions.UndefinedError: 'user' is undefined
127.0.0.1 - - [25/Jun/2022 10:06:52] "GET /?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 304 -
127.0.0.1 - - [25/Jun/2022 10:06:52] "GET /?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 304 -
127.0.0.1 - - [25/Jun/2022 10:06:52] "GET /?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 304 -
127.0.0.1 - - [25/Jun/2022 10:06:52] "GET /?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 304 -

thanks in advance for any help :)

CodePudding user response:

Pretty certain that code block has no visibility on the user.

href="{{ url_for('edit', id=user['id']) }}"

If you look at the flask tutorial, for things like post['username'], they are using a jinja loop to describe what post is referring to:

{% for post in posts %}
    <article >
      <header>
        <div>
          <h1>{{ post['title'] }}</h1>
          <div >by {{ post['username'] }} on {{ post['created'].strftime('%Y-%m-%d') }}</div>
        </div>
        {% if g.user['id'] == post['author_id'] %}
          <a  href="{{ url_for('blog.update', id=post['id']) }}">Edit</a>
        {% endif %}
      </header>
      <p >{{ post['body'] }}</p>
    </article>
    {% if not loop.last %}
      <hr>
    {% endif %}
  {% endfor %}

https://flask.palletsprojects.com/en/2.1.x/tutorial/blog/

So you'll need something like this:

{% if g.user %}
...
{% endif %}

https://flask.palletsprojects.com/en/2.1.x/tutorial/templates/

to pass the user object to the nav banner code block.

  • Related