bigblind
bigblind

Reputation: 12867

what's the best way to set computed property of app engine model in appengine after fetch from datastore?

I have my own User model in app engine, which should have a property of his gravatar url. However, since this can be very quickly computed using his email address, it doesn't make sense to store it. Is there a way to just automatically initialize this property when it s loaded from the datastore?

I could just add a method called get_avatar_url(), but you can't call an object's methods (as far as I know), from within a jinja2 template, and I don't want to post all these values individually to the template.

Upvotes: 0

Views: 632

Answers (3)

Nick Johnson
Nick Johnson

Reputation: 101149

You can define a method, as you describe, or you can define a property, like this:

class MyModel(db.Model):
  email = db.StringProperty(required=True)

  @property
  def avatar_url(self):
    return "http://gravatar.com/avatar/%s" % (hashlib.md5(self.email).hexdigest(),)

You can then refer to this as instance.avatar_url (or in a template, {{instance.avatar_url}}).

Either will work fine in a jinja2 template, but using a property is slightly neater if you need to request it elsewhere. Since only datastore property instances result in storing data in the datastore, your property will not be stored in the datastore.

Upvotes: 5

mlen108
mlen108

Reputation: 476

It's ok to call them from a template. All you need to do is to declare this model's method as classmethod or property

Here's a quick example:

# sample model
class UserProfile(db.Model):
    ...
    email = db.EmailProperty()
    ...

    @property
    def id(self):
        return self.key().id()

    @classmethod
    def get_avatar_url(self):
        # whatever you need to call gravatar url
        return self.email

# sample view
def show_user(user_id):
    user = User.all().filter("user = ", user_id).get()
    flowers = Flower.all().filter("user = ", user)
    return render_template('index.html', u=user, f=flowers)

# sample template
<div class="user">user id: {{ u.id }}, and gravatar: {{ u.get_gravatar_url() }}<div>

HTH.

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599610

You most certainly can call methods within a template. That is the best way to do it.

Upvotes: 0

Related Questions