Nikhil
Nikhil

Reputation: 5771

Custom constructors for models in Google App Engine (python)

I'm getting back to programming for Google App Engine and I've found, in old, unused code, instances in which I wrote constructors for models. It seems like a good idea, but there's no mention of it online and I can't test to see if it works. Here's a contrived example, with no error-checking, etc.:

class Dog(db.Model):
    name = db.StringProperty(required=True)
    breeds = db.StringListProperty()
    age = db.IntegerProperty(default=0)

    def __init__(self, name, breed_list, **kwargs):
        db.Model.__init__(**kwargs)
        self.name = name
        self.breeds = breed_list.split()

rufus = Dog('Rufus', 'spaniel terrier labrador')
rufus.put()

The **kwargs are passed on to the Model constructor in case the model is constructed with a specified parent or key_name, or in case other properties (like age) are specified. This constructor differs from the default in that it requires that a name and breed_list be specified (although it can't ensure that they're strings), and it parses breed_list in a way that the default constructor could not.

Is this a legitimate form of instantiation, or should I just use functions or static/class methods? And if it works, why aren't custom constructors used more often?

Upvotes: 4

Views: 1091

Answers (2)

Julian Go
Julian Go

Reputation: 4492

In your example, why not use the default syntax instead of a custom constructor:

rufus = Dog( name='Rufus', breeds=['spaniel','terrier','labrador'] )

Your version makes it less clear semantically IMHO.

As for overriding Model constructors, Google recommends against it (see for example: http://groups.google.com/group/google-appengine/browse_thread/thread/9a651f6f58875bfe/111b975da1b4b4db?lnk=gst&q=python+constructors#111b975da1b4b4db) and that's why we don't see it in Google's code. I think it's unfortunate because constructor overriding can be useful in some cases, like creating a temporary property.

One problem I know of is with Expando, anything you define in the constructor gets auto-serialized in the protocol buffer. But for base Models I am not sure what are the risks, and I too would be happy to learn more.

Upvotes: 2

Wooble
Wooble

Reputation: 89897

There's usually no need to do something like that; the default constructor will assign name, and when working with a list it almost always makes more sense to pass an actual list instead of a space-separated string (just imagine the fun if you passed "cocker spaniel" instead of just "spaniel" there, for one thing...).

That said, if you really need to do computation when instantiating a Model subclass instance, there's probably nothing inherently wrong with it. I think most people probably prefer to get the data into the right form and then create the entity, which is why you're not seeing a lot of examples like that.

Upvotes: 1

Related Questions