1

I am encountering a (probably) rookie mistake from inherited code within Flask. A helper function inside my template, url_for_other_page() is not being initialized when the page in question loads. Returns a self-descriptive error:

UndefinedError: 'url_for_other_page' is undefined

I know what's causing this -- the helper method is not getting polled because it's not exposed to the url in question, or something. What's the best approach to this without exposing more than is necessary to the URL path in question? Should the helper function be elsewhere in the application logic (such as in init?)

Below is the template snippet that causes the offending error, and the entire core.py, where the application logic lives. Requests are made to /images, which returns the results of entries_index() to the template call. This pagination code is pretty much co-opted from Flask's own examples. The full source can be viewed on Github if you need additional context.

core.py

import hashlib, os
from flask import request, session, render_template, flash, url_for, \
 redirect, send_from_directory
from werkzeug import secure_filename
from kremlin import app, db, dbmodel, forms, imgutils, uploaded_images
from pagination import Pagination
@app.route('/')
def home_index():
 """ Display the glasnost logo, attempt to replicate old behavior """
 return render_template('home.html')
@app.route('/images', defaults={'page': 1})
@app.route('/images/page/<int:page>')
def entries_index(page):
 """ Show an index of image thumbnails """
 posts = dbmodel.Post.query.all()
 pagination = Pagination(page, 2, len(posts))
 #import pdb; pdb.set_trace()
 return render_template('board.html', form=forms.NewPostForm(),
 posts=posts, pagination=pagination)
# The offending helper method
def url_for_other_page(page):
 args = request.view_args.copy()
 args['page'] = page
 return url_for(request.endpoint, **args)
 app.jinja_env.globals['url_for_other_page'] = url_for_other_page
@app.route('/images/<int:post_id>')
def view_post(post_id):
 """ Show post identified by post_id """
 post = dbmodel.Post.query.get_or_404(post_id)
 comments = dbmodel.Comment.query.filter_by(parent_post_id=post_id)
 return render_template('post.html', post=post, comments=comments)
@app.route('/images/get/<filename>')
def send_file(filename):
 """Send image file to browser"""
 return send_from_directory(app.config['UPLOADED_IMAGES_DEST'],
 filename)
@app.route('/images/add/', methods=['POST'])
def add_image():
 """ Add a new image """
 form = forms.NewPostForm()
 if form.validate_on_submit():
 filename = secure_filename(form.upload.file.filename)
 fileext = os.path.splitext(filename)[1]
 filedata = form.upload.file.stream.read()
 # Calculate SHA1 checksum
 h = hashlib.new('sha1')
 h.update(filedata)
 filehash = h.hexdigest()
 # Validate file uniqueness
 dupe = dbmodel.Image.query.filter_by(sha1sum=filehash).first()
 if dupe:
 flash("Image already exists: %s" % (dupe))
 return redirect(url_for('entries_index'))
 else:
 # File is unique, proceed to create post and image.
 # Save file to filesystem
 # Rewind file, it was read() by the SHA1 checksum
 # routine
 form.upload.file.seek(0)
 # Proceed with storage
 try:
 uploaded_images.save(storage=form.upload.file,
 name=''.join([filehash, '.']),
 )
 # FIXME: generate thumbnail in a safer way.
 # This is fairly horrible and I'm sorry.
 imagepath = uploaded_images.path(''.join([filehash, fileext]))
 imgutils.mkthumb(imagepath)
 except IOError:
 flash("Oh god a terrible error occured while saving %s" %
 (filename))
 else:
 dbimage = dbmodel.Image(filename, filehash)
 db.session.add(dbimage)
 user = None
 if "uid" in session:
 user = dbmodel.User.query.filter_by(
 id=session['uid']
 ).first()
 note = form.note.data
 #TODO: Implement tags.
 # Create a new post with the image
 post = dbmodel.Post(image=dbimage, title=filename,\
 note=note, user=user)
 db.session.add(post)
 # Commit database transaction
 db.session.commit()
 flash("Image successfully posted!")
 return redirect(url_for('entries_index'))
 else:
 flash("Your form has terrible errors in it.")
 return(redirect(url_for("entries_index")))

template call (excerpt from board.html)

<div id='ImageboardPageTop'>
 <div class=pagination>
 {% for page in pagination.iter_pages() %}
 {% if page %}
 {% if page != pagination.page %}
 <a href="{{ url_for_other_page(page) }}">{{ page }}</a>
 {% else %}
 <strong>{{ page }}</strong>
 {% endif %}
 {% else %}
 <span class=ellipsis>...</span>
 {% endif %}
 {% endfor %}
 {% if pagination.has_next %}
 <a href="{{ url_for_other_page(pagination.page + 1) 
 }}">Next &raquo;</a>
 {% endif %}
 </div>
</div>
asked Jul 8, 2015 at 4:45

1 Answer 1

1

This line needs to go into your core.py , not inside the function - url_for_other_page -

app.jinja_env.globals['url_for_other_page'] = url_for_other_page

Code -

def url_for_other_page(page):
 args = request.view_args.copy()
 args['page'] = page
 return url_for(request.endpoint, **args)
app.jinja_env.globals['url_for_other_page'] = url_for_other_page
answered Jul 8, 2015 at 5:02
Sign up to request clarification or add additional context in comments.

Comments

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.