Hi all :) I have the following problem.
I have a function that do some get_or_create on model X giving as parameters the field Y and Z. The same function is running on different threads, so it can happen that more get_or_create on model X and fields Y/Z are called at the same time. It can also happen that the values of Y/Z are the same in the different threads and here it comes the problem: it happens that get_or_create says it returned more than one row for X-Y/Z. Now Y/Z are not unique in my model and I do not have an overloading of the save function, but I think I can have the same problem if Y/Z were unique too. Looking at the DB I have more than one row with same values...how comes this? Here the get_or_create... def get_or_create(self, **kwargs): """ Looks up an object with the given kwargs, creating one if necessary. Returns a tuple of (object, created), where created is a boolean specifying whether an object was created. """ assert len(kwargs), 'get_or_create() must be passed at least one keyword argument' defaults = kwargs.pop('defaults', {}) try: return self.get(**kwargs), False except self.model.DoesNotExist: params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) params.update(defaults) obj = self.model(**params) obj.save() return obj, True Well...looking at the function I can say it happens in this way (and I did by debug too) : time 1 : T1 (thread 1) call get_or_create and does the self.get and it goes in exception for DoesNotExists time 2 : T2 do the same and goes in exception too for the same reason time 3 : T1 goes on with the exception and creates the object and gives it back time 4 : T2 the same (creating another one!) time 5 : any T (T1 or T2 or T3) who calls get_or_create again with same X-Y/Z...the self.get gets crazy. If the Y/Z were unique I just think the whole thing would fail at time 4...a little bit different, but still a problem. I could solve all the thing in this way, but I hope there is a better solution that I'm missing : from threading import Lock lock = Lock() def get_or_create(self, **kwargs): """ Looks up an object with the given kwargs, creating one if necessary. Returns a tuple of (object, created), where created is a boolean specifying whether an object was created. """ assert len(kwargs), 'get_or_create() must be passed at least one keyword argument' defaults = kwargs.pop('defaults', {}) try: return self.get(**kwargs), False except self.model.DoesNotExist: lock.acquire() try : try : res = self.get(**kwargs), False except self.model.DoesNotExist: params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) params.update(defaults) obj = self.model(**params) obj.save() res = obj, True except Exception, e: lock.release() raise e lock.release() return res --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---