I’m implementing Simpleauth by Alex on my App Engine (Python 2.7) app: https://github.com/crhym3/simpleauth and I can’t figure out why I’m getting a 404 error.
When I try to go to ‘/profile’ when not logged in, I get properly re-directed to ‘/’. But when I log in (successfully) and get directed to ‘/profile’ I get a 404.
I assume this is because it hits the “TemplateNotFound” exception in the ‘render’ code. But the “profile.html” file exists and is properly in the ‘templates’ directory.
Could anyone please help me figure out what I’m doing wrong?
Here is the code on the relevant files:
app.yaml
handlers:
- url: /auth/*
script: main.app
- url: /profile
script: main.app
- url: /logout/*
script: main.app
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
main.py
import webapp2
import jinja2
from secrets import SESSION_KEY
template_env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.getcwd()))
class MainHandler(webapp2.RequestHandler):
def get(self):
template = template_env.get_template('templates/home.html')
context = {
}
self.response.out.write(template.render(context))
app_config = {
'webapp2_extras.sessions': {
'cookie_name': '_simpleauth_sess',
'secret_key': SESSION_KEY
},
'webapp2_extras.auth': {
'user_attributes': []
}
}
app = webapp2.WSGIApplication([('/', MainHandler),
webapp2.Route('/profile', handler='handlers.ProfileHandler', name='profile'),
webapp2.Route('/auth/<provider>', handler='handlers.AuthHandler:_simple_auth', name='auth_login'),
webapp2.Route('/auth/<provider>/callback', handler='handlers.AuthHandler:_auth_callback', name='auth_callback'),
webapp2.Route('/logout', handler='handlers.AuthHandler:logout', name='logout')], config=app_config, debug=True)
handlers.py (unchanged from Alex’s Simpleauth code!)
import webapp2
from webapp2_extras import auth, sessions, jinja2
from jinja2.runtime import TemplateNotFound
from simpleauth import SimpleAuthHandler
class BaseRequestHandler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
@webapp2.cached_property
def jinja2(self):
"""Returns a Jinja2 renderer cached in the app registry"""
return jinja2.get_jinja2(app=self.app)
@webapp2.cached_property
def session(self):
"""Returns a session using the default cookie key"""
return self.session_store.get_session()
@webapp2.cached_property
def auth(self):
return auth.get_auth()
@webapp2.cached_property
def current_user(self):
"""Returns currently logged in user"""
user_dict = self.auth.get_user_by_session()
return self.auth.store.user_model.get_by_id(user_dict['user_id'])
@webapp2.cached_property
def logged_in(self):
"""Returns true if a user is currently logged in, false otherwise"""
return self.auth.get_user_by_session() is not None
def render(self, template_name, template_vars={}):
# Preset values for the template
values = {
'url_for' : self.uri_for,
'logged_in' : self.logged_in
}
# Add manually supplied template values
values.update(template_vars)
# read the template or 404.html
try:
self.response.write(self.jinja2.render_template(template_name, **values))
except TemplateNotFound:
self.abort(404)
def head(self, *args):
"""Head is used by Twitter. If not there the tweet button shows 0"""
pass
class ProfileHandler(BaseRequestHandler):
def get(self):
"""Handles GET /profile"""
if self.logged_in:
self.render('profile.html', {
'user': self.current_user,
'session': self.auth.get_user_by_session()
})
else:
self.redirect('/')
The problem above is that I was using two different ways of implementing Jinja2. The two different methods are discussed in a separate question: Which is the preferred method to use jinja2 on App Engine?
It was the mixing and matching that was causing the 404 error.