thanks for the detailed reply - I now understand the issue. And yes, I did 
read the documentation, but did not absorb it properly. Use of pyscopg1 is due 
to inertia. When I was first using django I had a lot of legacy code using 
psycopg1 and it was too much of a bother to migrate. That code is no longer my 
responsibility now, so I will probably shift. Am top posting as there is 
nothing specific to reply to. Thanks again.

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
> 
> 
> "Any keyword arguments passed to get_or_create() -- except an optional one
> called defaults -- will be used in a get() call."
> 
> So with the arguments as you have passed them, get_or_create is looking for
> a model with name='me' and num=2, and since one does not exist, it is going
> to go down the path of attempting to create an instance with those values.
> Since you have specified at the database level that name must be unique,
> that is not going to work: attempting to create a 2nd row with an
> already-existing name value is going to raise an IntegrityError.
> 
> To accomplish what you want, you need to move num into the defaults
> argument, so that it will not be used on the get() lookup, but will be used
> if the get fails to find a match and an object needs to be created. That
>  is:
> 
> Tm.objects.get_or_create(name='me', defaults={'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'
> 
> Here you are running into a bug in the postgresql backend.  Is there some
> reason you are using the old psycopg1 backend instead of the psycopg2 one?
> The latter is really a much better choice at this point.
> 
> Anyway, what has happened here is the get_or_create code has gone down the
> path of trying to create the new object, which has failed because of the
> unique constraint on name. It is trying to rollback to the
> previously-created savepoint, but that is failing due to a bug that was
> fixed yesterday in r12848 (trunk) and r12849 (1.1.X branch).  So to avoid
> this you could either simply switch to the psycopg2 backend (which did not
> have the bug) or update to a latest trunk or 1.1.X Django code.
> 
> Note when you fix the call to get_or_create to properly specify which of
>  the values must be used on the get() part of get_or_create(), you won't be
>  going down this path as you are now, so you likely won't see this
>  exception during basic testing even if you don't change backends or update
>  to latest Django code. However, you could still go down this path
>  legitimately -- if two threads "simultaneously" attempt to create an
>  object with the same name, both may see that it does not exist and try to
>  create it. Only one will succeed, and the other will go down this path.
>  You'll need this path to work properly in order for the 2nd thread to be
>  able to retrieve the object created by the other thread. So even if you
>  notice that fixing the get_or_create call makes this other exception go
>  away, you should still update the code you are using, if you want the call
>  to behave correctly in all situations.
> 
> Karen
> 

-- 
regards
Kenneth Gonsalves
Senior Associate
NRC-FOSS
http://certificate.nrcfoss.au-kbc.org.in

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to