Code

Opened 6 years ago

Closed 6 years ago

Last modified 5 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 kmtracey)

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/

Attachments (0)

Change History (8)

comment:1 Changed 6 years ago by kenkam

  • Cc kenkam@… added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 6 years ago by kmtracey

  • Description modified (diff)

Reformatted description.

comment:3 Changed 6 years ago by kmtracey

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

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

comment:5 Changed 6 years ago by badri

  • Cc sholombc@… added
  • Resolution set to invalid
  • Status changed from new to closed
  • Triage Stage changed from Unreviewed to Accepted

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

  • Resolution invalid deleted
  • Status changed from closed to reopened

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 6 years ago by mtredinnick

  • Resolution set to invalid
  • Status changed from reopened to closed

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 5 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.