I am getting the following error when I try to goto index.html on my site. The site was templated from 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 ' % \ (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> <form action="" method="post" name="post"> {{ form.hidden_tag() }} <div> <label for="post">{{ _('Say something:') }}</label> <div> {{ form.post(size=30, maxlength=140) }} {% for error in form.post.errors %} <span>[{{ error }}]</span><br> {% endfor %} </div> </div> <div> <div> <input type="submit" value="{{ _('Post!') }}"> </div> </div> </form> </div> {% for post in posts.items %} {% include 'post.html' %} {% endfor %} <ul> {% if posts.has_prev %} <li><a href="{{ url_for('index', page=posts.prev_num) }}">{{ _('Newer posts') }}</a></li> {% else %} <li><a href="#">{{ _('Newer posts') }}</a></li> {% endif %} {% if posts.has_next %} <li><a href="{{ url_for('index', page=posts.next_num) }}">{{ _('Older posts') }}</a></li> {% else %} <li><a href="#">{{ _('Older posts') }}</a></li> {% endif %} </ul>
{% endblock %}post.html
<table> <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>{{ post.body }}</span></strong></p> {% if post.language != None and post.language != '' and post.language != g.locale %} <div> <span> <a href="javascript:translate('{{ post.language }}', '{{ g.locale }}', '#post{{ post.id }}', '#translation{{ post.id }}', '#loading{{ post.id }}');">{{ _('Translate') }}</a> </span> <img 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 - 0 1 Answer
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) 2