By the way, theres a wiki page on Udacity about NDB vs DB: http://forums.udacity.com/cs253/questions/30012/gae-db-vs-ndb?page=1&focusedAnswerId=30058#30058
On Friday, July 6, 2012 12:16:31 AM UTC+1, mma wrote: > > Guido, thanks for taking the time to respond. > > You're right on ComputedProperty. I used it the wrong way. See more about > that: > http://stackoverflow.com/questions/11324435/ndb-badrequesterror-only-in-production/11324606#comment14917060_11324606 > > You're right also on the "asides". I'm not using that part and will remove > it from the code. > > PS: As you might have guessed, I'm a newbie on Python and on App Engine > Python. First contact was thru Udacity's CS 101 and CS 253 (web apps). I > get things to work, but some part of the code is not professional. I do > unit testing, though -- learned it by watching Misko Hevery videos. > > > On Thursday, July 5, 2012 10:46:00 AM UTC+1, Guido van Rossum wrote: >> >> On Wednesday, July 4, 2012 1:59:49 AM UTC+2, mma wrote: >>> >>> Hi there. >>> >>> I get the following error only on production: BadRequestError: BLOB, >>> ENITY_PROTO or TEXT properties must be in a raw_property field >>> >>> It happens when I put() a instance of the Receipt class (extends >>> ndb.Model) >>> >>> Below, I attach the model and the handler where the code breaks (only in >>> production) >>> >>> >>> class Receipt(RModel): >>> ownerId = ndb.IntegerProperty() >>> houseId = ndb.IntegerProperty() >>> renterId = ndb.IntegerProperty() >>> year = ndb.IntegerProperty() >>> month_number = ndb.IntegerProperty() >>> code = ndb.StringProperty() >>> description = ndb.StringProperty() >>> value = ndb.StringProperty() >>> >>> owner = ndb.ComputedProperty(lambda self: Owner.get_by_id(self.ownerId)) >>> house = ndb.ComputedProperty(lambda self: House.get_by_id(self.houseId)) >>> renter = ndb.ComputedProperty(lambda self: >>> Renter.get_by_id(self.renterId)) >>> month = ndb.ComputedProperty(lambda self: >>> month_number_to_string(self.month_number)) >>> >> >> These ComputedProperties look suspicious. The owner, house and renter >> lambdas return entities; are you sure you don't mean to return their keys >> instead? E.g. Owner.get_by_id(id) loads an Owner entity (which is a >> blocking datastore call). If you just want to store the key, you can use >> ndb.Key(Owner, id) instead. >> >> If you really want to store these as entities, it's possible that you can >> get away by declaring the ComputedProperty as indexed=False. But you're >> probably better off declaring them as e.g. StructuredProperty(Owner), and >> if you want them filled in automatically, you could do that in a pre-post >> hook. >> >> >>> >>> class RModel(ndb.Model): >>> created = ndb.DateTimeProperty(auto_now_add = True) >>> changed = ndb.DateTimeProperty(auto_now_add = True) >>> creatorId = ndb.IntegerProperty() >>> changerId = ndb.IntegerProperty() >>> >>> #def to_dict(self): >>> # return ndb.to_dict(self, {'id':self.key().id()}) >>> >> >> Aside: What are you trying to do here? I think maybe you meant this: >> >> def to_dict(self): >> result = super(RModel, self).to_dict() >> result['id'] = self.key.id() >> return result >> >> ??? >> >> >>> >>> def set_attributes(self, **attrs): >>> props = self.properties() >>> for prop in props.values(): >>> if prop.name in attrs: >>> prop.__set__(self, attrs[prop.name]) >>> >> >> Aside: this looks like code from old db. Its equivalent is >> ent.populate(**attrs), except the latter complains if you specify a keyword >> that has no corresponding property. >> >>> >>> >>> class ReceiptNew(BaseHandler): >>> def Get(self): >>> user_id = self.get_user_id() >>> owner = Owner.get_by_id(user_id) >>> receipt = Receipt(value="") >>> houses = list(House.gql("where ownerId = :1", owner.key.id())) >>> renters = list(Renter.gql("where ownerId = :1", owner.key.id())) >>> context = {'receipt': receipt, 'houses': houses, 'renters': renters, >>> 'new': True} >>> self.render_response('receipt-edit.html', **context) >>> >>> def post(self): >>> user_id = self.get_user_id() >>> owner = Owner.get_by_id(user_id) >>> >>> data = { >>> 'year': self.request.get('year'), >>> 'month': self.request.get('month'), >>> 'house': self.request.get('house'), >>> 'renter': self.request.get('renter'), >>> 'value': self.request.get('value'), >>> 'paid': self.request.get('paid') >>> } >>> >>> receipt = Receipt() >>> receipt.year = int(data.get('year')) >>> receipt.month_number = int(data.get('month')) >>> receipt.houseId = int(data.get('house')) >>> receipt.renterId = int(data.get('renter')) >>> receipt.value = data.get('value') >>> receipt.ownerId = owner.key.id() >>> receipt.put() # code breaks here, only in production >>> self.redirect('/receipts') >>> >>> -- You received this message because you are subscribed to the Google Groups "Google App Engine" group. To view this discussion on the web visit https://groups.google.com/d/msg/google-appengine/-/s5mG6flZNJUJ. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en.
