We can control 404 errors and bad requests using the abort() function provided by flask.
What it does is that it lets us end a request.
[app.py]
from flask import (Flask, g, render_template, flash, redirect, url_for,
abort)
...
@app.route('/stream')
@app.route('/stream/')
def stream(username=None):
template = 'stream.html'
if username and username != current_user.username:
try:
user = models.User.select().where(models.User.username**username).get()
except models.DoesNotExist:
abort(404)
else:
stream = user.posts.limit(100)
else:
stream = current_user.get_stream().limit(100)
user = current_user
if username:
template = "user_stream.html"
return render_template(template, stream=stream, user=user)
@app.route('/follow/')
@login_required
def follow():
try:
to_user = models.User.get(models.User.username**username)
except models.DoesNotExist:
abort(404)
else:
try:
models.Relationship.create(from_user=g.user._get_current_object(), to_user=to_user)
except IntegrityError:
pass
else:
flash("You have successfully followed {}!".format(to_user.username), "success")
return redirect(url_for('stream', username=to_user.username))
@app.route('/unfollow/')
@login_required
def unfollow():
try:
to_user = models.User.get(models.User.username**username)
except models.DoesNotExist:
abort(404)
else:
try:
models.Relationship.get(from_user=g.user._get_current_object(), to_user=user).delete_instance()
except IntegrityError:
pass
else:
flash("You have unfollowed {}.".format(to_user.username), "success")
return redirect(url_for('stream', username=to_user.username))
@app.route('/post/')
def view_post(post_id):
if post_id:
posts = models.Post.select().where(models.Post.id==post_id)
if posts.count() == 0:
abort(404)
return render_template('stream.html', stream=posts)
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
...
abort(404)
A function that Flask uses to end a view early and throw an error.
If you know HTTP status code, 404 is File Does Not Exist
if posts.count() == 0:
abort(404)
If we don’t get any records that match the post id we won’t get the models.DoesNotExist error, because we’re using a .select().where() filter instead of .get(). So we have to check for the record using this approach.
@app.errorhandler(404)
def not_found(error)
Anytime a 404 is triggered, our app will use the not_found function, where it renders the 404.html template and passes the 404 error.
[404.html]
{% extends "layout.html" %}
{% block content %}
<h1>404</h1>
<p>Sorry, that page does not exist.</p>
<p><a href="{{ url_for('index') }}">Try again</a></p>
{% endblock %}
Nothing out of the ordinary here.