Django 1.0 is
out and so far I like it a lot. I worked through the tutorials and other than my html 101 skills, all seems fairly straightforward.
I thought I would write an app to access my local install of one of the
ensembl databases to see what Django can offer for legacy dbs. Note that Django has a short tutorial page on
legacy dbs. I'm skipping over the part where I point the Django settings to my local db...
What we do is set up the basic project structure as in the tutorial, then added my app (djpyensembl). With no excuse for poor directory/project/app naming I set up:
~/django_ensembl
/djensembl
/__init__.py
/djpyensembl <-- this is my app
/manage.py
/settings.py
/urls.pyNow, to create the models from an existing db, we use the "inspectdb" option for manage.py. Running "
python manage.py inspectdb > models.py" will output the model statements as figured out by Django looking at the ensembl tables. Moving the models.py file into the djpyensembl app directory puts the models in the right place.
What happens next caught me off guard. I figured I'd jsut start the Django dev server using "
python manage.py runserver 8080". This is what I got:
Validating models...
Unhandled exception in thread started by
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/django/core/management/commands/runserver.py", line 48, in inner_run
self.validate(display_num_errors=True)
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/django/core/management/base.py", line 126, in validate
raise CommandError("One or more models did not validate:\n%s" % error_text)
django.core.management.base.CommandError: One or more models did not validate:
djpyensembl.interpro: "id": You can't use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.Turns out the interpro table in ensembl is set up in a way that's not conducive to Django.
mysql> desc interpro;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| interpro_ac | varchar(40) | NO | PRI | | |
| id | varchar(40) | NO | PRI | | |
+-------------+-------------+------+-----+---------+-------+mysql> select * from interpro limit 1;
+-------------+---------+
| interpro_ac | id |
+-------------+---------+
| IPR000001 | PF00051 |
+-------------+---------+mysql> SHOW CREATE TABLE interpro;
+----------+---------------------------------------------+
| Table | Create Table |
+----------+---------------------------------------------+
interpro | CREATE TABLE `interpro` (
`interpro_ac` varchar(40) NOT NULL default '',
`id` varchar(40) NOT NULL default '',
UNIQUE KEY `interpro_ac` (`interpro_ac`,`id`),
KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+----------+---------------------------------------------+There is no real primary key for the table and one of the fields is called 'id'. From what I can tell, this is the only table that uses a plain 'id' name as a column name and also from what I can tell, this seems a poor naming choice. Not knowing much about the nature of the entries in interpro and not planning on using them for this demo, I enter hack mode and immediately assign 'id' as the primary key.
mysql> ALTER TABLE interpro ADD PRIMARY KEY(id);
Query OK, 18220 rows affected (0.75 sec)
Records: 18220 Duplicates: 0 Warnings: 0As a result of this, I need to update my Interpro model in ~/django_ensembl/djensembl/djpyensembl/models.py (the file created by inspectdb). Before the update, it looked like this:
class Interpro(models.Model):
interpro_ac = models.CharField(unique=True, max_length=120)
id = models.CharField(max_length=120)
class Meta:
db_table = u'interpro'It now looks like:
class Interpro(models.Model):
interpro_ac = models.CharField(unique=True, max_length=120)
id = models.CharField(primary_key=True, max_length=120)
class Meta:
db_table = u'interpro'Now when I run "
python manage.py runserver 8080", the models will validate.
More on this later...