Reputation: 11038
I'm trying to mimic Django's unique_together
feature, but I can't seem to get it straight
class MyClass(ndb.Model):
name = 'name'
surname = 'surname'
phone = 'phone'
def get_unique_key(self):
return self.name + "|" + self.surname + "|" + self.phone
"Yeah, pretty easy" NOT
According to the accepted answer in this post, simply assigning the id
param in the obj constructor was enough. But I don't want to handle that in a view. Ideally, I'd do this:
object = MyClass()
object = object.custom_populating_method(form.cleaned_data)
object.id = object.get_unique_key()
object.put()
Or even better, place that in a _pre_put_hook
, so that the id
would be set as last thing before saving (and maybe do some checking enforcing the uniqueness of the data across the datastore).
Apparently, I was wrong. The only way to achieve this is by hacking the view:
unique_id = "|" + form.cleaned_data['bla'] + "|" + form.cleaned_data ...
object = MyClass(id=unique_id)
which is awful and completely wrong (since every change to the model's requirements needs to be inspected also in the views). Plus, I'd end up doing a couple of ugly calls to fetch some related data. I've spent too much time, probably, on this problem to see an exit and I really hope I'm missing something obvious here, but I can't really find any good example nor proper documentation around this subject. Has anyone any hint or experience with something similar?
tl;dr: is there a nice way to achieve this without adding unnecessary code to my views?
(I'm "using" Django and ndb's Models on the Datastore)
Thanks
Upvotes: 2
Views: 205
Reputation: 12986
Use a factory or class method to construct the instance.
class MyClass(ndb.Model):
name = ndb.StringProperty()
surname = ndb.StringProperty()
phone = ndb.StringProperty()
@staticmethod
def get_unique_key(name,surname,phone):
return '|'.join((name,surname,phone))
@classmethod
@transactional
def create_entity(cls,keyname,name,surname,phone):
key = ndb.Key(cls, cls.get_uniquekey())
ent = key.get()
if ent:
raise SomeDuplicateError()
else:
ent = cls(key=key, name=name,surname=surname,phone=phone)
ent.put()
newobj = MyClass.create_entity(somename, somesurname, somephone)
Doing it this way allows you to also ensure the key is unique by creatin the key and tring to fetch it first.
Upvotes: 2
Reputation: 755
I think you can do it if you assign the entire key
, rather than just the id
:
object = MyClass()
object = object.custom_populating_method(form.cleaned_data)
object.key = ndb.Key(MyClass, object.get_unique_key())
object.put()
Upvotes: 0