views:

95

answers:

3

I want to require that one of my model classes specify my own custom key as the key_name, that way I can always rely on it being there. How can I require this? For example, I may have a model class such as:

class Account(db.Model):
    user = db.UserProperty(required=True)
    email = db.EmailProperty()

And I want to require that key_name is always specified, requiring instantiation in a manner such as the following:

    user_obj = users.get_current_user()
    new_user = Account(user=user_obj, key_name=user.user_id())
    new_user.put()

How can this be done? Thanks in advance

+1  A: 

You can make all instantiation of the Account model go through a simple factory function (maybe name the class itself _Account to clarify to other coders on the project that the class itself is meant to be private):

def make_account(key_name=None, **k):
    if key_name is None:
        raise ValueError('Must specify key_name for account!')
    return _Account(key_name=key_name, **k)

You can get more sophisticated and do it in a classmethod in class Account (overriding the latter's __init__ with some checks to make it impossible to accidentally call from elsewhere), &c, but this is the core idea: "do it in your application-level code".

Alex Martelli
Thanks, this is exactly what I ended up doing.
Cuga
+2  A: 

You can create a base class like models on jaikuengine.

class BaseModel (db.Model):
    def __init__(self, parent=None, key_name=None, _app=None, **kw):
        if not key_name and 'key' not in kw:
            key_name = self.key_from(**kw)

        super(BaseModel, self).__init__(
            parent, key_name=key_name, _app=_app, **kw)

        if not key_name:
            key_name = self.key_from(**kw)

    @classmethod
    def key_from(cls, **kw):
        if hasattr(cls, 'key_template'):
            try:
                return cls.key_template % kw
            except KeyError:
                logging.warn(u'Automatic key_name generation failed: %s <- %s',
                              cls.key_template,
                              kw)
                return None

class Account (BaseModel):
    user = db.UserProperty(required=True)
    email = db.EmailProperty()

    key_template = "account/%(user)s"
sahid
A: 

Here is another example on how to require and also validate a key_name: Validator for the Model key_name property in Google App Engine datastore (Python)

famzah