1
votes

I am using Endpoints-proto-datastore written by Danny Hermes for Google App Engine and need help figuring out how to update an entity.. My model for what I need to update is the following

class Topic(EndpointsModel):
    #_message_fields_schema = ('id','topic_name','topic_author')
    topic_name = ndb.StringProperty(required=True)
    topic_date = ndb.DateTimeProperty(auto_now_add=True)
    topic_author = ndb.KeyProperty(required=True)
    topic_num_views = ndb.IntegerProperty(default=0)
    topic_num_replies = ndb.IntegerProperty(default=0)
    topic_flagged = ndb.BooleanProperty(default=False)
    topic_followers = ndb.KeyProperty(repeated=True)
    topic_avg_rating = ndb.FloatProperty(default=0.0)
    topic_total_rating = ndb.FloatProperty(default=0.0)
    topic_num_ratings = ndb.IntegerProperty(default=0)
    topic_raters = ndb.KeyProperty(repeated=True)

And as you can see, the rating properties have a default of 0. So each time a topic is rated, I need to update each of the rating properties. However, none of my properties is the actual rating being provided by the user. How can i pass in the value the user rated the topic to be able to update the properties in the model? Thanks!

1
Danny here. You essentially want two things -- the rater and the rating -- to be sent? From topic_raters I surmise the rater would be a KeyProperty and the rating would be a float or int?bossylobster
@bossylobster Yes, thats correct. I need to pass in the key of the user's profile entity that I use for extending user object which is the model called UserProfile. And I need to pass in the rating the user selected. I am also using the Endpoints JavaScript client library that I set up if that changes anything. So given that a user gives a rating of 3 out of 5, I need to add 3 to total_rating, 1 to num_ratings, and update avg_rating based on those two. Then add the user's profile key to raters. Thanks!vt-cwalker

1 Answers

1
votes

You can do this by having an "alias" property called rating associated with your UserModel:

from endpoints_proto_datastore.ndb import EndpointsAliasProperty

class UserModel(EndpointsModel):

    ...

    def rating_set(self, value):
        # Do some validation
        self._rating = value

    @EndpointsAliasProperty(setter=rating_set)
    def rating(self):
        return self._rating

This will allow ratings to be sent with UserModels in requests but won't require those ratings to be stored.

You're better off using the OAuth 2.0 token for the user and calling endpoints.get_current_user() to determine who the user is in the request.

Something like a dedicated model for ratings could be much easier:

from endpoints_proto_datastore.ndb import EndpointsUserProperty

class Rating(EndpointsModel):
    rater = EndpointsUserProperty(raise_unauthorized=True)
    rating = ndb.IntegerProperty()
    topic = ndb.KeyProperty(kind=Topic)

and then transactionally retrieving the Topic from the datastore and updating it in a request method decorated by @Rating.method.