Opened 8 years ago

Closed 8 years ago

Last modified 8 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: UI/UX:

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 Changed 8 years ago by Kenneth Kam

Cc: kenkam@… added

comment:2 Changed 8 years ago by Karen Tracey

Description: modified (diff)

Reformatted description.

comment:3 Changed 8 years ago by Karen Tracey

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 Changed 8 years ago by sholombc@…

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

comment:5 Changed 8 years ago by Badri

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 Changed 8 years ago by sholombc@…

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 Changed 8 years ago by Malcolm Tredinnick

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 Changed 8 years ago by (none)

milestone: post-1.0

Milestone post-1.0 deleted

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