datatype exception in simple GAE form using datastore

Go To StackoverFlow.com

2

I am an absolutely newb to GAE and am trying my first sample application. I have written a simple HTMl form. on clicking submit, the details in the fields need to be saved in the datastore.

My problem is that I am getting datatype exceptions and i have no idea where i am going wrong

import cgi
import datetime
import urllib
import wsgiref.handlers
import os
from google.appengine.ext.webapp import template

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class Champion(db.Model):
    champion_first_name = db.StringProperty()
    champion_last_name = db.StringProperty()
    champion_email = db.EmailProperty()
    champion_phone_code = db.IntegerProperty()
    champion_phone_number = db.IntegerProperty()
    diabetic_first_name = db.StringProperty()
    diabetic_last_name = db.StringProperty()
    diabetic_age = db.IntegerProperty()
    diabetic_gender = db.StringProperty()
    diabetic_email = db.EmailProperty()
    diabetic_phone_code = db.IntegerProperty()
    diabetic_phone_number = db.IntegerProperty()
    diabetic_city = db.StringProperty()
    diabetic_zipcode = db.IntegerProperty()
    diabetic_since = db.IntegerProperty()
    diabetic_relationship = db.StringProperty()
    checkup_date = db.DateProperty ()
    md_advert_feedback = db.StringProperty()
    timestamp = db.DateTimeProperty(auto_now_add=True)

class MainPage(webapp.RequestHandler):
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'main.html')
        self.response.out.write(template.render(path, template_values))

    def post(self):
        pledge_data = Champion(champion_first_name = cgi.escape(self.request.get('champ_first_name')),
                    champion_last_name = cgi.escape(self.request.get('champ_last_name')),
                    champion_email = cgi.escape(self.request.get('champ_email')),
                    champion_phone_code = cgi.escape(self.request.get('champ_phone_code')),
                    champion_phone_number = cgi.escape(self.request.get('champ_phone_number')),
                    diabetic_first_name = cgi.escape(self.request.get('diab_first_name')),
                    diabetic_last_name = cgi.escape(self.request.get('diab_last_name')),
                    diabetic_age = cgi.escape(self.request.get('diab_age')),
                    diabetic_gender = cgi.escape(self.request.get('diab_gender')),
                    diabetic_email = cgi.escape(self.request.get('diab_email')),
                    diabetic_phone_code = cgi.escape(self.request.get('diab_phone_code')),
                    diabetic_phone_number = cgi.escape(self.request.get('diab_phone_number')),
                    diabetic_city = cgi.escape(self.request.get('diab_city')),
                    diabetic_zipcode = cgi.escape(self.request.get('diab_zip')))
                    # diabetic_since = cgi.escape(int(self.request.get('diab_since'))))
                    # diabetic_relationship = cgi.escape(self.request.get('diab_relationship')),
                    # md_advert_feedback = cgi.escape(self.request.get('md_ad_feedback'))
                    # checkup_date = cgi.escape(self.request.get('checkup_date')),
                    # )

        pledge_data.put()


application = webapp.WSGIApplication([
    ('/', MainPage),
], debug=True)


def main():
  run_wsgi_app(application)


if __name__ == '__main__':
  main()

The error i am getting is

Traceback (most recent call last):
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\webapp\_webapp25.py", line 703, in __call__
    handler.post(*groups)
  File "C:\Users\Rishav\Documents\Google App Engine\helloworld\main.py", line 54, in post
    diabetic_zipcode = cgi.escape(self.request.get('diab_zip')))
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\db\__init__.py", line 945, in __init__
    prop.__set__(self, value)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\db\__init__.py", line 599, in __set__
    value = self.validate(value)
  File "C:\Program Files (x86)\Google\google_appengine\google\appengine\ext\db\__init__.py", line 3141, in validate
    % (self.name, type(value).__name__))
BadValueError: Property champion_phone_number must be an int or long, not a unicode

I am absolutely certain the answer is gonna make me faceplam, but i am just not getting it now. I believe I have put in the correct db model. also, it makes no difference if I actually input any data in the webform form field or not. I get the same error even when i leave the fields null and then hit submit.

EDIT: OP here. in case anyone is interested in what i did; once I converted all required field data to int, i found another error. I would get valueerror eception if any of my fields had null value. Now i want to leave all my data entry validation on the client side. so i changed my code to;

def post(self):
    pledge_data = Champion()
    try:
        pledge_data.champion_first_name = cgi.escape(self.request.get('champ_first_name'))
        pledge_data.champion_last_name = cgi.escape(self.request.get('champ_last_name'))
        pledge_data.champion_email = cgi.escape(self.request.get('champ_email'))
        pledge_data.champion_phone_code = int(cgi.escape(self.request.get('champ_phone_code')))
        pledge_data.champion_phone_number = int(cgi.escape(self.request.get('champ_phone_number')))
        pledge_data.diabetic_first_name = cgi.escape(self.request.get('diab_first_name'))
        pledge_data.diabetic_last_name = cgi.escape(self.request.get('diab_last_name'))
        pledge_data.diabetic_age = int(cgi.escape(self.request.get('diab_age')))
        pledge_data.diabetic_gender = cgi.escape(self.request.get('diab_gender'))
        pledge_data.diabetic_email = cgi.escape(self.request.get('diab_email'))
        pledge_data.diabetic_phone_code = int(cgi.escape(self.request.get('diab_phone_code')))
        pledge_data.diabetic_phone_number = int(cgi.escape(self.request.get('diab_phone_number')))
        pledge_data.diabetic_city = cgi.escape(self.request.get('diab_city'))
        pledge_data.diabetic_zipcode = int(cgi.escape(self.request.get('diab_zip')))
        pledge_data.diabetic_since = int(cgi.escape(self.request.get('diab_since')))
                # diabetic_relationship = cgi.escape(self.request.get('diab_relationship')),
                # md_advert_feedback = cgi.escape(self.request.get('md_ad_feedback'))
                # checkup_date = cgi.escape(self.request.get('checkup_date')),
                # )
    except ValueError:
        pass

    pledge_data.put()
2012-04-04 16:53
by Rishav Sharan
+1 for including a relevant code sample and full traceback. Thank you - bernie 2012-04-04 17:00
and thank you for adding in the python tag. forgot that. : - Rishav Sharan 2012-04-04 17:21
no worries. it wasn't necessary until they added Go and Java support : - bernie 2012-04-04 17:24
Why would you want to store a phone number as an integer? This seems like a Very Bad Idea(tm) - Wooble 2012-04-04 18:21
Phone numbers aren't integers - trying to store them that way is a bad idea. Likewise, you should do escaping on output, not on input (as in your last code snippet) - Nick Johnson 2012-04-05 05:16


2

The quick fix is to explicitly cast, e.g.:

...
champion_phone_number = int(cgi.escape(self.request.get('champ_phone_number'))),
...
2012-04-04 16:59
by bernie
If you see one of my commented lines contains;

    # diabetic_since = cgi.escape(int(self.request.get('diab_since'))))

it was what i tried the very first time i got the error. i have used int inside the cgi.escape clause. -_- /facepalm - Rishav Sharan 2012-04-04 17:29

And that's OK! You are not your code. We all do stuff like that. Get out there and get that next bug! My guess: it's going to be a much more difficult one to solve - bernie 2012-04-04 17:32


1

all request arguments are strings. if you need the property is of another type like champion_phone_number you need to explicitly transform it into an int()

2012-04-04 17:24
by aschmid00
Ads