Summary
When a field class named "Vehicle" is attempted to be used as a foreign key, the SQL generated by django is incorrect.
Changing the name of the class to "Vahicle" or some other misspelling that does not begin with "Veh" results in the correct behavior.
Example
The following model definition does not work as expected. (N.B. I've trimmed some code to reduce the model definition to its essential bug-revealing form.)
from django.db import models
import datetime
class Vehicle(models.Model):
type = models.CharField(maxlength=15) # e.g. truck, car
manufacturer = models.CharField(maxlength=15) # e.g. Volkswagen, Isuzu
theModel = models.CharField(maxlength=15) # e.g. Passat, Trooper
year = models.IntegerField()
def __str__(self):
return repr(self.year) + ' ' + self.manufacturer + ' ' + self.theModel
class Route(models.Model):
locFrom = models.CharField('Starting Location', maxlength=15)
locTo = models.CharField('Destination', maxlength=15)
def __str__(self):
return self.locFrom + ' to ' + self.locTo
class Trip(models.Model):
vehicle = models.ForeignKey(Vehicle)
route = models.ForeignKey(Route)
def __str__(self):
return repr(self.start) + ' ' + repr(self.route) + ' ' + repr(self.vehicle)
The models.py file is in the commuteTime app in the commute project
yoshiAshi:django$ ls -al commute
total 56
drwxr-xr-x 11 gerry gerry 374 Apr 30 23:58 .
drwxr-xr-x 8 gerry gerry 272 May 1 08:33 ..
-rw-r--r-- 1 gerry gerry 0 Apr 30 07:38 __init__.py
-rw-r--r-- 1 gerry gerry 157 Apr 30 08:07 __init__.pyc
drwxr-xr-x 9 gerry gerry 306 May 1 08:33 commuteTime
drwxr-xr-x 3 gerry gerry 102 Apr 30 23:32 db
-rw-r--r-- 1 gerry gerry 546 Apr 30 07:38 manage.py
-rw-r--r-- 1 gerry gerry 2828 Apr 30 23:06 settings.py
-rw-r--r-- 1 gerry gerry 1824 Apr 30 23:06 settings.pyc
-rw-r--r-- 1 gerry gerry 227 Apr 30 07:38 urls.py
yoshiAshi:django$ ls -al commute/commuteTime
total 48
drwxr-xr-x 9 gerry gerry 306 May 1 08:33 .
drwxr-xr-x 11 gerry gerry 374 Apr 30 23:58 ..
-rw-r--r-- 1 gerry gerry 0 Apr 30 08:10 __init__.py
-rw-r--r-- 1 gerry gerry 169 Apr 30 23:01 __init__.pyc
drwxr-xr-x 3 gerry gerry 102 Apr 30 08:13 db
-rw-r--r-- 1 gerry gerry 876 May 1 08:13 models.py
-rw-r--r-- 1 gerry gerry 2312 May 1 08:13 models.pyc
-rw-r--r-- 1 gerry gerry 26 Apr 30 08:10 views.py
Testing the SQL generation give this
yoshiAshi:commute$ python manage.py sql commuteTime
BEGIN;
CREATE TABLE "commuteTime_route" (
"id" integer NOT NULL PRIMARY KEY,
"locFrom" varchar(15) NOT NULL,
"locTo" varchar(15) NOT NULL
);
CREATE TABLE "commuteTime_trip" (
"id" integer NOT NULL PRIMARY KEY,
"vehicle_id" integer NOT NULL,
"route_id" integer NOT NULL REFERENCES "commuteTime_route" ("id")
);
CREATE TABLE "commuteTime_vehicle" (
"id" integer NOT NULL PRIMARY KEY,
"type" varchar(15) NOT NULL,
"manufacturer" varchar(15) NOT NULL,
"theModel" varchar(15) NOT NULL,
"year" integer NOT NULL
);
COMMIT;
Note that the commuteTime_trip table does not have commuteTime_vehicle as a proper foreign key. We would expect
"vehicle_id" integer NOT NULL REFERENCES "commuteTime_vehicle" ("id"),
but instead get
"vehicle_id" integer NOT NULL,
Work-Around
Misspelling "Vehicle" results in the correct behavior. For example if the Vehicle class and foreign key reference are replaced by
class Vahicle(models.Model):
type = models.CharField(maxlength=15) # e.g. truck, car
manufacturer = models.CharField(maxlength=15) # e.g. Volkswagen, Isuzu
theModel = models.CharField(maxlength=15) # e.g. Passat, Trooper
year = models.IntegerField()
...
class Trip(models.Model):
vehicle = models.ForeignKey(Vahicle)
route = models.ForeignKey(Route)
...
the correct SQL is generated
yoshiAshi:commute$ python manage.py sql commuteTime
BEGIN;
CREATE TABLE "commuteTime_route" (
"id" integer NOT NULL PRIMARY KEY,
"locFrom" varchar(15) NOT NULL,
"locTo" varchar(15) NOT NULL
);
CREATE TABLE "commuteTime_vahicle" (
"id" integer NOT NULL PRIMARY KEY,
"type" varchar(15) NOT NULL,
"manufacturer" varchar(15) NOT NULL,
"theModel" varchar(15) NOT NULL,
"year" integer NOT NULL
);
CREATE TABLE "commuteTime_trip" (
"id" integer NOT NULL PRIMARY KEY,
"vehicle_id" integer NOT NULL REFERENCES "commuteTime_vahicle" ("id"),
"route_id" integer NOT NULL REFERENCES "commuteTime_route" ("id")
);
COMMIT;
I've experimented with different spellings: "Ve" gives the correct foreign key
definition, but "Veh" does not.
Weird.
Hardware and Software Configuration
Mac OS 10.4.9
python 2.3.5
django svn trunk revision 5127
Database: sqlite (for development server)
I started the discovery of this bug on another Mac running python 2.5, so I don't think it depends on the python version. I'll check later today, or maybe tonight, depending on when I get the time.