Opened 16 years ago

Closed 16 years ago

Last modified 16 years ago

#9269 closed (invalid)

get_or_create having issues

Reported by: sholombc@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.0
Severity: Keywords: get_or_create
Cc: kenkam@…, sholombc@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Karen Tracey)

when i used get_or_create

    p, created = Inventory.objects.get_or_create(product = pr, location = lo, storage_type = storagetype)
    if created:
        p.amount = amount1
        p.save()
    else:
        form.save()

it would fail on created, and then it would save the form and make 2 records in the database the second time it would give me a error that it found 2 of the same record

the model and form file: http://dpaste.com/81855/

the product model file: http://dpaste.com/81866/

the view code: http://dpaste.com/81855/

the code that works: http://dpaste.com/81867/

Change History (8)

comment:1 by Kenneth Kam, 16 years ago

Cc: kenkam@… added

comment:2 by Karen Tracey, 16 years ago

Description: modified (diff)

Reformatted description.

comment:3 by Karen Tracey, 16 years ago

You've got the same link for "the model and form file" and "the view code". It seems to be "the model and form file", so "the view code" is missing.

comment:4 by sholombc@…, 16 years ago

sorry the view code is http://dpaste.com/81854/ (was very tired :) ).

comment:5 by Badri, 16 years ago

Cc: sholombc@… added
Resolution: invalid
Status: newclosed
Triage Stage: UnreviewedAccepted

p, created = Inventory.objects.get_or_create(product = pr, location = lo, storage_type = storagetype)
executes a query which matches more than one object.
This raises an exception in django/db/models/query.py line 304..
you will either have to:

1.make your get_or_create query more specific by giving more parameters.
2.handle the exception. something like:
try:

p, created = Inventory.objects.get_or_create(product = pr, location = lo, storage_type = storagetype)

except Inventory.MultipleObjectsReturned:

# do something here

for instance, I have reproduced the same error from one of your models:

l1 = Location(name='foo1', description='bar')
l2 = Location(name='foo2', description='bar')
obj, created = Location.objects.get_or_create(description='bar')
l1.save()
l2.save()
obj, created = Location.objects.get_or_create(description='bar')

Traceback (most recent call last):

File "<console>", line 1, in <module>
File "/usr/local/lib/python2.5/site-packages/django/db/models/manager.py", line 96, in get_or_create

return self.get_query_set().get_or_create(kwargs)

File "/usr/local/lib/python2.5/site-packages/django/db/models/query.py", line 326, in get_or_create

return self.get(kwargs), False

File "/usr/local/lib/python2.5/site-packages/django/db/models/query.py", line 305, in get

% (self.model._meta.object_name, num, kwargs))

MultipleObjectsReturned: get() returned more than one Location -- it returned 2! Lookup parameters were {'description': 'bar'}

comment:6 by sholombc@…, 16 years ago

Resolution: invalid
Status: closedreopened

the problem is not that it returns 2 records. the problem is that the first time it doesn't succeed in returning 1 record, which causes it to create a duplicate in the database, but when i do the same lookup a second time it returns 2 records with a error.

p, created = Inventory.objects.get_or_create(product = pr, location = lo, storage_type = storagetype)
    if created:
        p.amount = amount1
        p.save()
    else:
        form.save()

on the first try it will always go to the else: and do form.save() therefor creating a duplicate with the same parameters (product, location,and storage type). instead of changing the amount and saving the record p.save() .

comment:7 by Malcolm Tredinnick, 16 years ago

Resolution: invalid
Status: reopenedclosed

I think you are misunderstanding how get_or_create() works. You are saying that it returns with created=False, which means that the record already existed in the database (and is returned as p). So then you save another copy. Since there aren't any unique constraints on your model to say it's illegal to save something with duplicate (product, location, storage_type) combinations, the save works and a subsequent filtering will retrieve multiple objects. That's all working as expected.

The second element of the tuple returned from get_or_create() is only true when a new element is created. It's false if an existing element is retrieved. I can't see that there's any bug here from what you have described. If you're still having trouble understanding that behaviour, perhaps you could construct a shorter example (the current one has a lot of code to wade through) and post a question to django-users to get more help. Trac isn't really useful as a forum for explaining that sort of stuff, however, from your description, things appear to be working as expected.

comment:8 by (none), 16 years ago

milestone: post-1.0

Milestone post-1.0 deleted

Note: See TracTickets for help on using tickets.
Back to Top