A GET Request is being sent twice when a User clicks a link in a Google App Engine, Python App. The App uses webapp2 and jinja2.
This only happens if a Blobstore image is missing from the Datastore Model, "Event". If the image is present in "Event", there is only one GET Request recorded in Logs. If the blobstore image has not been uploaded by the User, then there is a second GET Request, which is returned with a NoneType Error.
The GET Requests are sending to the same Handler, "InfoHandler(BaseHandler)".
NDB Model:
class Event(ndb.Model):
"""datastore class for storing events"""
# : event properties
org_user = ndb.StringProperty() #ID string for the Organiser
poster_url = ndb.StringProperty() #blobstore image url
poster_key = ndb.StringProperty() #blobstore image key
....
BaseHandler:
def get_obj_from_url(self, position, kind):
""" returns a datastore object from a url"""
#: first get the url string
url_string = self.request.url
#: then split the string on POSITION to get the key value
key_value = url_string.split('/')[position]
#: now query to get the entity instance from the key value
qry = ndb.Key(kind, key_value)
#: finally you can get the datastore object
db_obj = qry.get()
return db_obj
events.py for rendering the page
class InfoHandler(BaseHandler):
"""handler to render the event info page"""
def get(self):
#: SET LOCALE
self.set_locale()
#: TEST FOR THE USER
user_id = self.user_obj()
if user_id:
if db_user.User.get_by_id(user_id):
#: get the user info from datastore
info = db_user.User.get_by_id(user_id)
#: get the event object from the datastore
event_obj = self.get_obj_from_url(-1, "Event")
org_user_id = event_obj.org_user
Logging Error Stack:
- [14/Mar/2015:07:20:13 -0700] "GET /events/event_info/None HTTP/1.1" 500 719 "http://www.x.com/events/event_info/example_event" "Mozilla/5.0 (Linux; Android 4.4.2; SM-T805 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.109 Safari/537.36" "www.x.com" ms=94 cpu_ms=76 cpm_usd=0.000080 app_engine_release=1.9.18 instance=00c61b117c03db016d0f4da5a9f36a8e9aea83fd
E 2015-03-14 15:20:13.235
'NoneType' object has no attribute 'org_user'
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/ webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~x/0-9-9-9- 4.382865846043625422/events/events.py", line 753, in get
org_user_id = event_obj.org_user
AttributeError: 'NoneType' object has no attribute 'org_user'
This Error doesn't affect the User, as the first GET Request returns the "Event" object, without the image, and the page is rendered without Errors. It is however a quirk that I would like to figure out.
Why is the GET Request being sent twice?
Thanks for your help.
Template Code:
def render_template(self, route, filename, template_values):
""" you need a function to render the template from jinja.
takes these inputs:
route - route to template folder
filename - the name of the template
template_values - the values returned in the template
"""
#: first you need to define the loader environment and extensions
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(route),
autoescape=True,
extensions=['jinja2.ext.i18n'])
#: you need to set gettext to retrieve translation from templates via the {{trans}} tag
jinja_env.install_gettext_translations(i18n)
#: you need to set the attribute, template, using the filename value
template = jinja_env.get_template(filename)
#: now you can output the template with the template_values
self.response.write(template.render(template_values))
Your question is missing critical information, how are the routes set up, where's the template code? The problem obviously comes from the client, where else could the request come from? You should be providing information on that front.
Anyway, for some weird reason I think I might know what it is...
I'm guessing when you render the page you have some img
tag with a url, and that url is event.poster_url
, which if uploaded will be whatever you got from get_serving_url
, but if that hasn't happened yet the value will be None
.
I'm also guessing the current location (in the browser, when the problem happens) is /events/event_info/
, and so in the 2nd case will cause a request to /events/event_info/None
.
Hoping my crystal ball works :)