python in Google App Engine - having the class-instead-of-instance problem, but using db.Model so can't create init method
i am writing an app to compare products, using Python and GAE. The products will belong to a set of similar products, and the app calculates the best value in each set.
When i create a new product, it can be added to an existing set or a new set can be created.
When testing the app, the first set gets created just fine. I populate an instance of the set with the name of the product. I use a form on one web page to POST the data into the "suppbook" page. I'm still not clear on how a web page can be a class but that's a different question.
There's more code around all of this but I'm trying to make my question as clear as possible.
class Supp(db.Model): name = db.StringProperty(multiline=False) # a bunch of other attributes using Google's DB Model class SuppSet(db.Model): name = db.StringProperty(default='') supp_list = set() # a bunch of other attributes using Google's DB Model # i tried to add this after reading a few questions on SO but GAE doesn't like it def __init__(self,): self.name = 'NoName' self.best_value = 'NoBestValue' self.supp_list = set() Class Suppbook(webapp.RequestHandler): def post(self): supp = Supp() suppSet = SuppSet() ... supp.name = self.request.get('name') supp.in_set = self.request.get('newset') suppSet.name = supp.in_set suppSet.supp_list.add(supp.name) self.response.out.write('%s now contains %s<p>' % (suppSet.name,suppSet.supp_list))
This works well the first time around, and if I only use one SuppSet, I can add many supps to it. If I create another SuppSet, though, both suppSets will have the same contents for their supp_list. I have been looking through the questions on here and I think (know) I'm doing something wrong regarding class vs. instance attribute access. I tried to create an __init__ method for SuppSet but GAE complained: AttributeError: 'SuppSet' object has no attribute '_entity'
Also, I am using the GAE datastore to put() and get() the Supps and SuppSets, so I'm not clear why I'm not acting on the unique instances that I should be pulling from the DB.
I am not sure if I am providing enough information but I wanted to get started on this issue. Please let me know if more info is needed to help debug this.
I'm also open to the idea that i'm going about this completely wrong. I'm considering re-writing the whole thing, but I'm so close to being "finished" with basic functionality that I'd like to try to solve this issue.
In your init you will need to call the super's init, db.Model has some important stuff to do in its init, you will have to match the signature.
However you likely shouldn't be setting up things like defaults in there. Try and just use the datastore Properties ability to set a default.
You've got some (I assume) typos in your code. Python is sensitive to case and white-space. The attribute names you use also don't match your defs, such as in_set. When possible, post actual working examples demonstrating your problem.
class Supp(db.Model): name = db.StringProperty(multiline=False) in_set = db.StringProperty(multiline=False) # your other stuff ... class SuppSet(db.Model): name = db.StringProperty(default='') supp_list = db.StringListProperty() # your other stuff ... # In Python, you need to explicitly call the parent's __init__ with your args. # Note that this is NOT needed here. def __init__(self, **kwargs): db.Model.__init__(self, **kwargs) class Suppbook(webapp.RequestHandler): def post(self): # This will create a NEW Supp and SuppSet every request, # it won't fetch anything from the datastore. # These are also NOT needed (included for explanation) supp = Supp() suppSet = SuppSet() # It sounds like you want something like: product_name = self.request.get('name') product_set = self.request.get('newset') # check for missing name / set: if not product_name or not product_set: # handle the error self.error(500) return # Build the keys and batch fetch. supp_key = db.Key.from_path('Supp', product_name) suppset_key = db.Key.from_path('SuppSet', product_set) supp, suppset = db.get([supp_key, suppset_key]) if not supp: supp = Supp(key_name=product_name, name=product_name) if not suppset: suppset = SuppSet(key_name=product_set, name=product_set) # Update the entities supp.in_set = product_set if product_name not in suppset.supp_list: suppset.supp_list.append(product_name) # Batch put... db.put([supp, suppset]) self.response.out.write('%s now contains %s<p>' % (suppset.name, str(suppset.supp_list)))