djangoproject.com | python.org | linux.com
demongin.org - Error Log

Error Log

Three mistakes I made today and how I corrected them; posted for posterity.


Saturday, 2010-01-16 | Django, Programming

"A woman may very well form a friendship with a man, but for this to endure, it must be assisted by a little physical antipathy."

Nietzsche

I spent most of this weekend working on a top-secret django project.

As usual, I screwed a bunch of stuff up before finally brute-forcing my ideas into print and getting my applications and views working correctly. What follows are three things I learned about python, django and postgresql today:

Automatic thumbnail width/height resizing with PIL

If you're using the python image library's built-in thumbnail function to resize images, you might not know that you only need to specify the width or the height when resizing. Say, for instance, you've got some thumbnail-creating code that looks like this and creates thumbnails 30 pixels wide and 50 pixels high:
    im = Image.open("/path/to/image")
    im.thumbnail((30,50), Image.ANTIALIAS)
Now, say you're not 100% sure that everything which could potentially get thumbnailed by that code is going to be at the same aspect ratio. All you've got to do is use the special "auto" value in your size tuple:
    size = (30, "auto")
    im.thumbnail(size, Image.ANTIALIAS)
And voila: the width is 30 pixels and the height is resized at 1:1. Nice.

'duplicate key value' violations in django

If, while working on a django project, you run manage.py syncdb and get an error that looks like the following:
psycopg2.IntegrityError: duplicate key value violates unique constraint "django_content_type_pkey"
And your logs look like this:
/var/log/postgresqltoconnell@jane:~/$ sudo tail -f /var/log/postgresql/postgresql-8.3-main.log
[sudo] password for toconnell: 
2010-01-16 09:21:39 EST ERROR:  duplicate key value violates unique constraint "django_content_type_pkey"
2010-01-16 09:21:39 EST STATEMENT:  INSERT INTO "django_content_type" ("name", "app_label", "model") VALUES (E'artist', E'disco', E'artist')
You've got two options: 1.) roll up your sleeves, fire up the psql monitor and start manually tampering with table data* or 2.) drop the database, load a backup and start over.

Basically, what happened here is that you ran django-admin startapp appname twice; i.e. you started an app of the same name twice and, when you went to add it to your application, with that syncdb command, you tripped a unique key constraint intended to prevent ambiguous calls to the database.

My Advice: drop the table and load the back-up--automatically created django database tables tend to dislike being tampered with.

Speaking of restoring postgres data...

When restoring data, remember to specify database name. If, for example, you do this:
# su postgres -c 'psql -f demongin.sql'
You'll end up copying all your tables to the postgres database; ye olde psql monitor, for better or for worse, always assumes that you want to use the database of the same name of the user that you're attempting to operate with.

A proper restore of a postgres dump looks like this:
# su postgres -c 'psql -f demongin.sql -d demongin'


* UPDATE: 2010-06-17


So, I got an email yesterday from a bloke called Leon Waldman who found this post after Googling the error string "duplicate key value violates unique constraint". In his email, Leon points out that you violate the "unique" constraint when DBName/Schemas/YourSchema/Sequences (which points to the current value on the auto-increment id field on one of the postgres system tables) somehow gets set to a value less than the current value. The violation happens when django tries to increment that id field by one.

Leon explains this with a simple hypothetical:
The last entry on my id field on the table django_content_type was set to 25, but the sequence for the auto increment for this field was set to 23....

So, when django tried to write a new value to this table, it calculated that the id should be 24 (23+1) and then fails to create the record because 24 already exists on this table.

To fix, I opened the sequence on DBName/Schemas/YourSchema/Sequences/django_content_type_id_seq and set the field "Current value" to 25.
Once you do that, the next new item created by django should have an id value of 26 and you should be good to go.

Thanks Leon.