I have a model like this:
name - unique
slno - not null
mode - not null
If the instance does not exist and I give all three values to get_or_create,
it works
if the instance exists, and I give values for slno and mode which are different
from the existing ones - I get a programming error as get_or_create tries to
create a new instance and falls foul of the unique constraint on name. It
works if I only give the value for name - it gets the instance and then I can
add the new values and save
if the instance does not exist and I only give the value for name, I get a
programming error that the not null constraints on slno and mode are violated.
so it looks to me that get_or_create will only work reliably when there are no
not null or unique constraints in the model. Or am I missing something?
--
regards
Kenneth Gonsalves
Senior Associate
NRC-FOSS
http://certificate.nrcfoss.au-kbc.org.in
I think you are missing the optional kwarg 'initial', which is a
dictionary of initial values to use when the instance does not exist.
So not
foo, created = Foo.objects.get_or_create(name=name,
sino=sino,mode=mode)
but
foo, created = Foo.objects.get_or_create(name=name,
initial={'sino': sino, 'mode': mode, })
Cheers
Tom
Actually the kwarg is 'defaults', not 'initial'.
See http://docs.djangoproject.com/en/1.1/ref/models/querysets/#get-or-create-kwargs
--
DR.
Indeed :/
coffee++
Cheers
Tom
I don't understand what you are saying here. If the instance exists (as
in, the filter parameters passed to get would return a single item),
that instance is returned and the default parameters are never
considered. So the values you pass for slno and mode are irrelevant. If
the equivalent get() call would not return anything, then the instance
does not exist and it's clear that the default parameter must contain
correct data that can be used to create a new object -- including not
violating any unique constraints. Perhaps you could show the code call
you are making, rather than writing it out as a sentence.
In short: get_or_create() first runs the get(). If that returns
something, it is what is returned. If the get() fails with no object
being present, then the instance DOES NOT exist and a new one is
created, with all the same requirements as if you'd created a new object
from scratch (e.g. no unique constraint violations).
Malcolm
He is describing this situation:
>>> User.objects.get(username='teva...@googlemail.com')
<User: teva...@googlemail.com>
>>> User.objects.get_or_create(username='teva...@googlemail.com')
(<User: teva...@googlemail.com>, False)
>>> User.objects.get(username='teva...@googlemail.com').first_name
u'Tom'
>>> User.objects.get(username='teva...@googlemail.com', first_name='Thomas')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "....site-packages/django/db/models/manager.py", line 119, in get
return self.get_query_set().get(*args, **kwargs)
File "....django/db/models/query.py", line 305, in get
% self.model._meta.object_name)
DoesNotExist: User matching query does not exist.
>>> User.objects.get_or_create(username='teva...@googlemail.com', first_name='Thomas')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "....site-packages/django/db/models/manager.py", line 122, in
get_or_create
return self.get_query_set().get_or_create(**kwargs)
File "....site-packages/django/db/models/query.py", line 343, in get_or_create
raise e
IntegrityError: (1062, "Duplicate entry '' for key 2")
IE, where Model.objects.get(**kwargs) does not return an object, but
Model.objects.create(**kwargs) would fail, which is fixed by knowing
about the 'defaults' kwarg to get_or_create:
>>> User.objects.get_or_create(username='teva...@googlemail.com',
... defaults={'first_name': 'Thomas', })
(<User: teva...@googlemail.com>, False)
Cheers
Tom
No, he's not, because Kenneth said that the instance exists. In your
example, the instance doesn't exist and thus a new object is attempted
to be created. The restrictions at that point are the same as when
creating a new object from scratch, as noted in my reply. The caller of
get_or_create() will always know what the various constraints are on the
model and must allow for that in their code.
Regards,
Malcolm
Actually, he described both situations where the instance exists, but
with different values for the non-key attributes of the model, and
where the instance doesn't exist.
pedant++
> example, the instance doesn't exist and thus a new object is attempted
> to be created. The restrictions at that point are the same as when
> creating a new object from scratch, as noted in my reply. The caller of
> get_or_create() will always know what the various constraints are on the
> model and must allow for that in their code.
>
> Regards,
> Malcolm
>
>
Well, quite. His problem was that he wasn't allowing for the
constraints in his code because he was unaware of the 'defaults' kwarg
to get_or_create(). With that addition, his problems when an instance
with the same unique key exists, and when no instance exists are both
fixed.
Cheers
Tom
sorry for not replying to this - for some reason all your recent mails have
gone to the spam folder! I only became aware of this mail when I saw a reply
to it. Here is what I mean - A simple model with two fields, 'name' is unique,
and 'num' is not null:
>>> Tm.objects.get_or_create(name='me',num=1)
(<Tm: me>, True)
>>> Tm.objects.get_or_create(name='me',num=2)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/lib/python2.6/django/db/models/manager.py", line 135, in
get_or_create
return self.get_query_set().get_or_create(**kwargs)
File "/usr/lib/python2.6/django/db/models/query.py", line 375, in
get_or_create
transaction.savepoint_rollback(sid, using=self.db)
File "/usr/lib/python2.6/django/db/transaction.py", line 242, in
savepoint_rollback
connection._savepoint_rollback(sid)
File "/usr/lib/python2.6/django/db/backends/__init__.py", line 61, in
_savepoint_rollback
self.cursor().execute(self.ops.savepoint_rollback_sql(sid))
File "/usr/lib/python2.6/django/db/backends/__init__.py", line 75, in cursor
cursor = self._cursor()
File "/usr/lib/python2.6/django/db/backends/postgresql/base.py", line 149,
in _cursor
cursor.execute("SET client_encoding to 'UNICODE'")
ProgrammingError: ERROR: current transaction is aborted, commands ignored
until end of transaction block
SET client_encoding to 'UNICODE'
Here is what I mean - A simple model with two fields, 'name' is unique,
and 'num' is not null:
>>> Tm.objects.get_or_create(name='me',num=1)
(<Tm: me>, True)
>>> Tm.objects.get_or_create(name='me',num=2)
Traceback (most recent call last):
[snip]
File "/usr/lib/python2.6/django/db/backends/__init__.py", line 61, in
_savepoint_rollback
self.cursor().execute(self.ops.savepoint_rollback_sql(sid))
File "/usr/lib/python2.6/django/db/backends/__init__.py", line 75, in cursor
cursor = self._cursor()
File "/usr/lib/python2.6/django/db/backends/postgresql/base.py", line 149,
in _cursor
cursor.execute("SET client_encoding to 'UNICODE'")
ProgrammingError: ERROR: current transaction is aborted, commands ignored
until end of transaction block
SET client_encoding to 'UNICODE'
On Friday 26 Mar 2010 4:55:39 pm Karen Tracey wrote:
> On Fri, Mar 26, 2010 at 1:49 AM, Kenneth Gonsalves <law...@au-kbc.org>wrote:
> > Here is what I mean - A simple model with two fields, 'name' is unique,
> >
> > and 'num' is not null:
> > >>> Tm.objects.get_or_create(name='me',num=1)
> >
> > (<Tm: me>, True)
> >
> > >>> Tm.objects.get_or_create(name='me',num=2)
>
> If you want get_or_create to return the instance with name 'me', regardless
> of the value of num which that instance may have, then you need to include
> the num value in the defaults argument to get_or_create, NOT as a bare
> keyword argument. From
> http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kw
> args
>
>
--
thanks for the detailed reply - I now understand the issue. And yes, I did
read the documentation, but did not absorb it properly.