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.