BuildError: Could not build url for endpoint 'user' with values ['nickname']. Did you forget to specify values ['page', 'username']?
The route calls for the variable username
to be defined, but you're passing a variable called nickname
in your post.html template.
flask.url_for('user', nickname=post.author.nickname)
needs to be changed to:
flask.url_for('user', username=post.author.nickname)
rockets4all
Updated on July 09, 2022Comments
-
rockets4all almost 2 years
I am getting the following error when I try to goto index.html on my site. The site was templated from https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins I modified it to take in usernames/passwords and got rid of openid. I went through and replaced nickname in the database with username and somehow it is still referencing it even after I have updated the database. I'm still new to this so please go easy. I searched for how to build url's and can't find anything I'm doing wrong.
BuildError: Could not build url for endpoint 'user' with values ['nickname']. Did you forget to specify values ['page', 'username']?
Here is most of the code to it, let me know and I'll post anything else relevant.
views.py
from flask import render_template, flash, redirect, session, url_for, request, \ g, jsonify from flask_login import login_user, logout_user, current_user, login_required from flask_sqlalchemy import get_debug_queries from flask_babel import gettext from datetime import datetime from guess_language import guessLanguage from app import app, db, lm, babel from .forms import EditForm, PostForm, SearchForm, RegistrationForm, LoginForm from .models import User, Post from .emails import follower_notification from .translate import microsoft_translate from config import POSTS_PER_PAGE, MAX_SEARCH_RESULTS, LANGUAGES, \ DATABASE_QUERY_TIMEOUT @lm.user_loader def load_user(id): return User.query.get(int(id)) @babel.localeselector def get_locale(): return request.accept_languages.best_match(LANGUAGES.keys()) @app.before_request def before_request(): g.user = current_user if g.user.is_authenticated: g.user.last_seen = datetime.utcnow() db.session.add(g.user) db.session.commit() g.search_form = SearchForm() g.locale = get_locale() @app.after_request def after_request(response): for query in get_debug_queries(): if query.duration >= DATABASE_QUERY_TIMEOUT: app.logger.warning( "SLOW QUERY: %s\nParameters: %s\nDuration: %fs\nContext: %s\n" % (query.statement, query.parameters, query.duration, query.context)) return response @app.errorhandler(404) def not_found_error(error): return render_template('404.html'), 404 @app.errorhandler(500) def internal_error(error): db.session.rollback() return render_template('500.html'), 500 @app.route('/', methods=['GET', 'POST']) @app.route('/index', methods=['GET', 'POST']) @app.route('/index/<int:page>', methods=['GET', 'POST']) @login_required def index(page=1): form = PostForm() if form.validate_on_submit(): language = guessLanguage(form.post.data) if language == 'UNKNOWN' or len(language) > 5: language = '' post = Post(body=form.post.data, timestamp=datetime.utcnow(), author=g.user, language=language) db.session.add(post) db.session.commit() flash(gettext('Your post is now live!')) return redirect(url_for('index')) posts = g.user.followed_posts().paginate(page, POSTS_PER_PAGE, False) return render_template('index.html', title='Home', form=form, posts=posts) @app.route('/register', methods=['GET', 'POST']) def register(): form = RegistrationForm(request.form) print("request.form=", request.form, "form.validate=", form.validate()) if request.method == 'POST' and form.validate(): print("BLANK") print(User.query.filter_by(username=form.username.data).first()) if User.query.filter_by(username=form.username.data).first() == None: user = User(username=form.username.data) user.hash_password(form.password.data) db.session.add(user) # make the user follow him/herself db.session.add(user.follow(user)) db.session.commit() flash('Thanks for registering') return redirect(url_for('login')) else: flash('Username already exists') return render_template('register.html', form=form) return render_template('register.html', form=form) @app.route('/login', methods=['GET', 'POST']) def login(): if g.user is not None and g.user.is_authenticated: return redirect(url_for('index')) form=LoginForm() if form.validate_on_submit(): session['remember_me'] = form.remember_me.data user=User.query.filter_by(username=form.username.data).first() if user and user.verify_password(form.password.data): if 'remember_me' in session: remember_me = session['remember_me'] session.pop('remember_me', None) login_user(user, remember=remember_me) flash("Logged in sucessfully.") '''eventually update to add security to redirects if not is_safe_url(next): return flask.abort(400) return redirect(request.args.get('next') or url_for('index')) ''' return redirect(request.args.get('next') or url_for('index')) flash("Incorrect username or password") return render_template('login.html', title='Sign In', form=form) ''' if g.user is not None and g.user.is_authenticated: return redirect(url_for('index')) form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(username).first() login_user(user) session['remember_me'] = form.remember_me.data return render_template('login.html', title='Sign In', form=form) ''' ''' @oid.after_login def after_login(resp): if resp.email is None or resp.email == "": flash(gettext('Invalid login. Please try again.')) return redirect(url_for('login')) user = User.query.filter_by(email=resp.email).first() if user is None: username = resp.username if username is None or username == "": username = resp.email.split('@')[0] username = User.make_valid_username(username) username = User.make_unique_username(username) user = User(username=username, email=resp.email) db.session.add(user) db.session.commit() # make the user follow him/herself db.session.add(user.follow(user)) db.session.commit() remember_me = False if 'remember_me' in session: remember_me = session['remember_me'] session.pop('remember_me', None) login_user(user, remember=remember_me) return redirect(request.args.get('next') or url_for('index')) ''' @app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('index')) @app.route('/user/<username>') @app.route('/user/<username>/<int:page>') @login_required def user(username, page=1): user = User.query.filter_by(username=username).first() if user is None: flash(gettext('User %(username)s not found.', username=username)) return redirect(url_for('index')) posts = user.posts.paginate(page, POSTS_PER_PAGE, False) return render_template('user.html', user=user, posts=posts, title='Your Profile') @app.route('/mobility', methods=['GET', 'POST']) @login_required def mobility(): return render_template('mobility.html') @app.route('/edit', methods=['GET', 'POST']) @login_required def edit(): form = EditForm(g.user.username) if form.validate_on_submit(): g.user.username = form.username.data g.user.about_me = form.about_me.data db.session.add(g.user) db.session.commit() flash(gettext('Your changes have been saved.')) return redirect(url_for('edit')) elif request.method != "POST": form.username.data = g.user.username form.about_me.data = g.user.about_me return render_template('edit.html', form=form) @app.route('/follow/<username>') @login_required def follow(username): user = User.query.filter_by(username=username).first() if user is None: flash('User %s not found.' % username) return redirect(url_for('index')) if user == g.user: flash(gettext('You can\'t follow yourself!')) return redirect(url_for('user', username=username)) u = g.user.follow(user) if u is None: flash(gettext('Cannot follow %(username)s.', username=username)) return redirect(url_for('user', username=username)) db.session.add(u) db.session.commit() flash(gettext('You are now following %(username)s!', username=username)) follower_notification(user, g.user) return redirect(url_for('user', username=username)) @app.route('/unfollow/<username>') @login_required def unfollow(username): user = User.query.filter_by(username=username).first() if user is None: flash('User %s not found.' % username) return redirect(url_for('index')) if user == g.user: flash(gettext('You can\'t unfollow yourself!')) return redirect(url_for('user', username=username)) u = g.user.unfollow(user) if u is None: flash(gettext('Cannot unfollow %(username)s.', username=username)) return redirect(url_for('user', username=username)) db.session.add(u) db.session.commit() flash(gettext('You have stopped following %(username)s.', username=username)) return redirect(url_for('user', username=username)) @app.route('/delete/<int:id>') @login_required def delete(id): post = Post.query.get(id) if post is None: flash('Post not found.') return redirect(url_for('index')) if post.author.id != g.user.id: flash('You cannot delete this post.') return redirect(url_for('index')) db.session.delete(post) db.session.commit() flash('Your post has been deleted.') return redirect(url_for('index')) @app.route('/search', methods=['POST']) @login_required def search(): if not g.search_form.validate_on_submit(): return redirect(url_for('index')) return redirect(url_for('search_results', query=g.search_form.search.data)) @app.route('/search_results/<query>') @login_required def search_results(query): results = Post.query.whoosh_search(query, MAX_SEARCH_RESULTS).all() return render_template('search_results.html', query=query, results=results) @app.route('/translate', methods=['POST']) @login_required def translate(): return jsonify({ 'text': microsoft_translate( request.form['text'], request.form['sourceLang'], request.form['destLang'])})
models.py
from hashlib import md5 import re from app import db from app import app from config import WHOOSH_ENABLED from passlib.apps import custom_app_context as pwd_context import sys if sys.version_info >= (3, 0): enable_search = False else: enable_search = WHOOSH_ENABLED if enable_search: import flask_whooshalchemy followers = db.Table( 'followers', db.Column('follower_id', db.Integer, db.ForeignKey('user.id')), db.Column('followed_id', db.Integer, db.ForeignKey('user.id')) ) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(32), index=True, unique=True) password_hash = db.Column(db.String(128)) email = db.Column(db.String(120), index=True, unique=True) posts = db.relationship('Post', backref='author', lazy='dynamic') about_me = db.Column(db.String(140)) last_seen = db.Column(db.DateTime) followed = db.relationship('User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') def hash_password(self, password): self.password_hash=pwd_context.encrypt(password) def verify_password(self, password): return pwd_context.verify(password, self.password_hash) @staticmethod def make_valid_username(username): return re.sub('[^a-zA-Z0-9_\.]', '', username) @staticmethod def make_unique_username(username): if User.query.filter_by(username=username).first() is None: return username version = 2 while True: new_username = username + str(version) if User.query.filter_by(username=new_username).first() is None: break version += 1 return new_username @property def is_authenticated(self): return True @property def is_active(self): return True @property def is_anonymous(self): return False def get_id(self): try: return unicode(self.id) # python 2 except NameError: return str(self.id) # python 3 def avatar(self, size): return 'http://www.gravatar.com/avatar/%s?d=mm&s=%d' % \ (md5(self.email.encode('utf-8')).hexdigest(), size) def follow(self, user): if not self.is_following(user): self.followed.append(user) return self def unfollow(self, user): if self.is_following(user): self.followed.remove(user) return self def is_following(self, user): return self.followed.filter( followers.c.followed_id == user.id).count() > 0 def followed_posts(self): return Post.query.join( followers, (followers.c.followed_id == Post.user_id)).filter( followers.c.follower_id == self.id).order_by( Post.timestamp.desc()) def __repr__(self): # pragma: no cover return '<User %r>' % (self.username) class Post(db.Model): __searchable__ = ['body'] id = db.Column(db.Integer, primary_key=True) body = db.Column(db.String(140)) timestamp = db.Column(db.DateTime) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) language = db.Column(db.String(5)) def __repr__(self): # pragma: no cover return '<Post %r>' % (self.body) #if enable_search: # whooshalchemy.whoosh_index(app, Post)
index.html
<!-- extend base layout --> {% extends "base.html" %} {% block content %} <h1>{{ _('Hi, %(username)s!', username=g.user.username) }}</h1> {% include 'flash.html' %} <div class="well"> <form class="form-horizontal" action="" method="post" name="post"> {{ form.hidden_tag() }} <div class="control-group{% if form.post.errors %} error{% endif %}"> <label class="control-label" for="post">{{ _('Say something:') }}</label> <div class="controls"> {{ form.post(size=30, maxlength=140) }} {% for error in form.post.errors %} <span class="help-inline">[{{ error }}]</span><br> {% endfor %} </div> </div> <div class="control-group"> <div class="controls"> <input class="btn btn-primary" type="submit" value="{{ _('Post!') }}"> </div> </div> </form> </div> {% for post in posts.items %} {% include 'post.html' %} {% endfor %} <ul class="pager"> {% if posts.has_prev %} <li class="previous"><a href="{{ url_for('index', page=posts.prev_num) }}">{{ _('Newer posts') }}</a></li> {% else %} <li class="previous disabled"><a href="#">{{ _('Newer posts') }}</a></li> {% endif %} {% if posts.has_next %} <li class="next"><a href="{{ url_for('index', page=posts.next_num) }}">{{ _('Older posts') }}</a></li> {% else %} <li class="next disabled"><a href="#">{{ _('Older posts') }}</a></li> {% endif %} </ul> {% endblock %}
post.html
<table class="table table-hover"> <tr> <td width="70px"><a href="{{ url_for('user', username=post.author.username) }}"><img src="{{ post.author.avatar(70) }}" /></a></td> <td> {% autoescape false %} <p>{{ _('%(username)s said %(when)s:', username='<a href="%s">%s</a>' % (url_for('user', username=post.author.username), post.author.username), when=momentjs(post.timestamp).fromNow()) }}</p> {% endautoescape %} <p><strong><span id="post{{ post.id }}">{{ post.body }}</span></strong></p> {% if post.language != None and post.language != '' and post.language != g.locale %} <div> <span id="translation{{ post.id }}"> <a href="javascript:translate('{{ post.language }}', '{{ g.locale }}', '#post{{ post.id }}', '#translation{{ post.id }}', '#loading{{ post.id }}');">{{ _('Translate') }}</a> </span> <img id="loading{{ post.id }}" style="display: none" src="/static/img/loading.gif"> </div> {% endif %} {% if post.author.id == g.user.id %} <div><a href="{{ url_for('delete', id = post.id) }}">{{ _('Delete') }}</a></div> {% endif %} </td> </tr> </table>
forms.py
from flask_wtf import Form from flask_babel import gettext from wtforms import StringField, BooleanField, TextAreaField, PasswordField from wtforms.validators import DataRequired, Length, EqualTo from .models import User class LoginForm(Form): username = StringField('username', validators=[DataRequired()]) password = PasswordField('password', validators=[DataRequired()]) remember_me = BooleanField('remember_me', default=False) class RegistrationForm(Form): username=StringField('Username', validators=[Length(min=4, max=25)]) password = PasswordField('Password', validators=[DataRequired(), EqualTo('confirm', message='Passwords must match')]) confirm = PasswordField('Repeat Password') remember_me = BooleanField('remember_me', default=False) class EditForm(Form): username = StringField('username', validators=[DataRequired()]) about_me = TextAreaField('about_me', validators=[Length(min=0, max=140)]) def __init__(self, original_username, *args, **kwargs): Form.__init__(self, *args, **kwargs) self.original_username = original_username def validate(self): if not Form.validate(self): return False if self.username.data == self.original_username: return True if self.username.data != User.make_valid_username(self.username.data): self.username.errors.append(gettext( 'This username has invalid characters. ' 'Please use letters, numbers, dots and underscores only.')) return False user = User.query.filter_by(username=self.username.data).first() if user is not None: self.username.errors.append(gettext( 'This username is already in use. ' 'Please choose another one.')) return False return True class PostForm(Form): post = StringField('post', validators=[DataRequired()]) class SearchForm(Form): search = StringField('search', validators=[DataRequired()])
Here is the full error from the console
BuildError: Could not build url for endpoint 'user' with values ['nickname']. Did you forget to specify values ['page', 'username']? 127.0.0.1 - - [19/May/2017 10:30:22] "GET /index?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:30:22] "GET /index?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:30:22] "GET /index?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:30:22] "GET /index?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:30:22] "GET /index?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 - * Detected change in '/home/jsnyder10/Documents/45/app/views.py', reloading * Restarting with stat /home/jsnyder10/Documents/45/flask/local/lib/python2.7/site-packages/flask_whooshalchemy.py:18: ExtDeprecationWarning: Importing flask.ext.sqlalchemy is deprecated, use flask_sqlalchemy instead. import flask.ext.sqlalchemy as flask_sqlalchemy * Debugger is active! * Debugger PIN: 196-025-674 /home/jsnyder10/Documents/45/app/views.py:34: FlaskWTFDeprecationWarning: "flask_wtf.Form" has been renamed to "FlaskForm" and will be removed in 1.0. g.search_form = SearchForm() /home/jsnyder10/Documents/45/app/views.py:66: FlaskWTFDeprecationWarning: "flask_wtf.Form" has been renamed to "FlaskForm" and will be removed in 1.0. form = PostForm() 127.0.0.1 - - [19/May/2017 10:45:14] "GET /index HTTP/1.1" 500 - Traceback (most recent call last): File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1997, in __call__ return self.wsgi_app(environ, start_response) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app response = self.handle_exception(e) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception reraise(exc_type, exc_value, tb) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app response = self.full_dispatch_request() File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request rv = self.dispatch_request() File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask_login/utils.py", line 228, in decorated_view return func(*args, **kwargs) File "/home/jsnyder10/Documents/45/app/views.py", line 81, in index posts=posts) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/templating.py", line 134, in render_template context, ctx.app) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/templating.py", line 116, in _render rv = template.render(context) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/jinja2/environment.py", line 1008, in render return self.environment.handle_exception(exc_info, True) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/jinja2/environment.py", line 780, in handle_exception reraise(exc_type, exc_value, tb) File "/home/jsnyder10/Documents/45/app/templates/index.html", line 2, in top-level template code {% extends "base.html" %} File "/home/jsnyder10/Documents/45/app/templates/base.html", line 63, in top-level template code {% block content %}{% endblock %} File "/home/jsnyder10/Documents/45/app/templates/index.html", line 27, in block "content" {% include 'post.html' %} File "/home/jsnyder10/Documents/45/app/templates/post.html", line 3, in top-level template code <td width="70px"><a href="{{ url_for('user', nickname=post.author.nickname) }}"><img src="{{ post.author.avatar(70) }}" /></a></td> File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/helpers.py", line 333, in url_for return appctx.app.handle_url_build_error(error, endpoint, values) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/app.py", line 1805, in handle_url_build_error reraise(exc_type, exc_value, tb) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/flask/helpers.py", line 323, in url_for force_external=external) File "/home/jsnyder10/Documents/45/flask/lib/python2.7/site-packages/werkzeug/routing.py", line 1768, in build raise BuildError(endpoint, values, method, self) BuildError: Could not build url for endpoint 'user' with values ['nickname']. Did you forget to specify values ['page', 'username']? 127.0.0.1 - - [19/May/2017 10:45:14] "GET /index?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:45:14] "GET /index?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:45:14] "GET /index?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:45:14] "GET /index?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 - 127.0.0.1 - - [19/May/2017 10:45:15] "GET /index?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
-
rockets4all almost 7 yearsThanks for the help, I was looking at an old template in gedit and was editing the wrong code. I was about to go crazy with why i was getting this error even though the code it referenced didn't exist.
-
iFunction over 5 yearsWish you had left the original template up as it is impossible to follow this thread now as there is no error, it's not possible to see how this was fixed