Modelforms for appengine models with WTForms and debugging with pdb

The post assumes you have basic familiarity with google appengine and python. If not and you are curious, please head over to this beginner tutorial i wrote, and then come back. In this post lets talk about using WTForms with Google App Engine. WTForms provides an out of the box support for App Engine and App Engine Models. In the latest version of appengine as per the latest release docs djangoforms is not supported but third-party alternatives such as WTForms can be used. So lets take a deeper look into how we deal with WTForms.

Lets get started with a minimal database model for app engine.

 from google.appengine.ext import db
 class Project(db.Model):
      title = db.StringProperty()
      description = db.TextProperty()
      start_date = db.DateProperty()
      target_finish_date = db.DateProperty()

      def __repr__(self):
        return unicode(self.title)

 class Ticket(db.Model):
    title = db.StringProperty()
    description = db.TextProperty()
    status = db.StringProperty(choices=set(["proposed", "ongoing", "finished"]))              
    priority = db.IntegerProperty()
    project = db.ReferenceProperty(Project)

    def __repr__(self):
        return unicode(self.title)

As is clear from the database schema, we have designed a database for a simple project management app. There can be tickets assigned to a project. The only thing to take a closer look is returning the title, this is done keeping in mind that the dropdown, generated by the modelforms does not show the object string rather the title of the project. So that it is easier for the users to choose the project.

Now lets handle the get and post request in our handler.

 class CreateForm(Webapp2.RequestHandler):


    def get(self):
        form = model_form(Ticket)
        self.render_template('index.html', {'form': form()})

    def post(self):
        form = model_form(Ticket)
        form_object = form(formdata=self.request.POST)
        if not form_object.errors and form_object.validate():
            model_obj = Ticket()
            form_object.populate_obj(model_obj)
            model_obj.save()
            return webapp2.redirect('/')
        else:
            print form_object.errors
            print form_object.validate()

In the above snippets we have written a simple request handler. If the request is of type GET we render the form, in case it is post, we assign the post data to the form also we perform the checks that the data coming is valid and that form has no errors. We then assign the data to the model object and save it. That solves most of the issues for us.

However, if you are more interested in exploring, and want to debug stuff. One way is to log things at every stage and see for yourselves each of the values. If not, you can use pdb, with the following hack, but make sure you don't have it while deploying.

import pdb for attr in ('stdin', 'stdout', 'stderr'): setattr(sys, attr, getattr(sys, '__%s__' % attr)) ''' put the above lines towards the beginning put the line below, where you want to get started with shell''' pdb.set_trace()

ipdb could have been a lot more comfortable and handy, but there is an open issue,
which has been acknowledged, hopefully people are working on it. You can also experiment with ndb models. They offer richer features. Hope the post helped in some way or other.

Comments

blog comments powered by Disqus