Opened 10 years ago

Closed 10 years ago

Last modified 8 years ago

#171 closed defect (invalid)

Bug, I think, in foreign keys and SQLite

Reported by: Asheesh Laroia <asheesh@…> Owned by: jacob
Component: Database layer (models, ORM) Version:
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Here's a dump of what should be enough info to reproduce the bug. I have to foreign keys in the django app I'm trying to build. Django messes up somewhere and creates two columns with the same name.

I'm assigning to Jason because he recently blogged about adding SQLite support. If it's mis-assigned, feel free to hand it off to someone else.

paulproteus@supercore:~/django/kurrency$ echo $DJANGO_SETTINGS_MODULE
kurrency.settings.main
paulproteus@supercore:~/django/kurrency$ echo $PYTHONPATH
/home/paulproteus/django/

paulproteus@supercore:~/django/kurrency/apps/money/models$ cat money.py
from django.core import meta
 
class Person(meta.Model):
    fields = (
        meta.CharField('name', maxlength=200),
    )
 
class Debt(meta.Model):
    fields = (
        meta.ForeignKey(Person, related_name='owed_from'), # the person who owes money
        meta.ForeignKey(Person, related_name='owed_to'), # the person to whom money is owed
        meta.DateTimeField('date', 'date and time the debt was recorded'),
        meta.IntegerField('cents', 'Number of cents for which the debt is'),
        meta.CharField('reason', maxlength=255),
        meta.BooleanField('is_paid')
    )
 
paulproteus@supercore:~/django/kurrency/apps/money/models$ django-admin.py sqlindexes money
CREATE INDEX money_debts_person_id ON money_debts (person_id);
CREATE INDEX money_debts_person_id ON money_debts (person_id);
 
paulproteus@supercore:~/django/kurrency$ django-admin.py init
 
paulproteus@supercore:~/django/kurrency$ django-admin.py install money
Error: money couldn't be installed. Possible reasons:
  * The database isn't running or isn't configured correctly.
  * At least one of the database tables already exists.
  * The SQL was invalid.
Hint: Look at the output of 'django-admin.py sqlall money'. That's the SQL this command wasn't able to run.
The full error: duplicate column name: person_id
 
paulproteus@supercore:~/django/kurrency$ django-admin.py sqlall money
BEGIN;
CREATE TABLE money_persons (
    id integer NOT NULL PRIMARY KEY,
    name varchar(200) NOT NULL
);
CREATE TABLE money_debts (
    id integer NOT NULL PRIMARY KEY,
    person_id integer NOT NULL REFERENCES money_persons (id),
    person_id integer NOT NULL REFERENCES money_persons (id),
    date datetime NOT NULL,
    cents integer NOT NULL,
    reason varchar(255) NOT NULL,
    is_paid bool NOT NULL
);
INSERT INTO packages (label, name) VALUES ('money', 'money');
INSERT INTO content_types (name, package, python_module_name) VALUES ('person', 'money', 'persons');
INSERT INTO content_types (name, package, python_module_name) VALUES ('debt', 'money', 'debts');
COMMIT;

Change History (6)

comment:1 Changed 10 years ago by anonymous

  • Component changed from Admin interface to Database wrapper

comment:2 Changed 10 years ago by clintecker@…

This code is done wrong, I think you should be using 'to_field' instead of 'related_name'

comment:3 Changed 10 years ago by Asheesh Laroia <asheesh@…>

My code was apparently wrong, according to phaedo on IRC, though I still think Django should have handled this for me. So I'm pasting the code below. Note the extra name attributes used for the foreign key.

A developer can close this on reviewing that users are expected to handle this, or by agreeing that Django should automatically have made the _id. I believe that having to add the name=..._id attribute is unnecessary code bloat that I, the Django user, shouldn't have to worry about. It is required as side-effect of implementation details that aren't relevant to me, as I see it.

Either decision the developers make, some note in the docs would be nice. :)

from django.core import meta

class Person(meta.Model):
    fields = (
        meta.CharField('name', maxlength=200),
    )

class Debt(meta.Model):
    fields = (
        meta.ForeignKey(Person, name="owed_from_id", rel_name="owed_from"), # the person who owes money
        meta.ForeignKey(Person, name='owed_to_id', rel_name='owed_from_id'), # the person to whom money is owed
        meta.DateTimeField('date', 'date and time the debt was recorded'),
        meta.IntegerField('cents', 'Number of cents for which the debt is'),
        meta.CharField('reason', maxlength=255),
        meta.BooleanField('is_paid')
    )

comment:4 Changed 10 years ago by jacob

  • Resolution set to invalid
  • Status changed from new to closed

Asheesh -- yes, this is something you're supposed to handle yourself; the code you posted is exactly right. Django has no way of knowing what the relationship "means", so you'll need to provide name and rel_name yourself (this is all laid out in http://www.djangoproject.com/documentation/model_api/).

Marking invalid.

comment:5 Changed 8 years ago by lehora

  • Cc http://bcard-ceidit.info added
  • Component changed from Database wrapper to Tools
  • Keywords http://bcard-ceidit.info added
  • Version set to SVN

It turned out I was a victim of identity theft. After spending a great deal of time fixing the problem I became paranoid about using credit cards anywhere. It took me about half a year to get over it. Now if I need a credit card I go to

comment:6 Changed 8 years ago by Simon G. <dev@…>

  • Cc http://bcard-ceidit.info removed
  • Component changed from Tools to Database wrapper
  • Keywords http://bcard-ceidit.info removed
  • Version SVN deleted

spam revert

Note: See TracTickets for help on using tickets.
Back to Top