#28824 closed New feature (wontfix)

Allow different Foreign Keys to share same underlying DB column

Reported by: klass-ivan Owned by: nobody
Component: Database layer (models, ORM) Version: 1.11
Severity: Normal Keywords: foreigh key, db_column,
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

class A(Model):
    uid = CharField(unique=True)
    # other fields

class B(Model):
    uid = CharField(unique=True)
    # other fields

class C(Model):
   # other fields
   uid  = CharField(unique=False)
   a = ForeignKey(to=A, to_field='uid', db_column='uid', null=True)
   b = ForeignKey(to=B, to_field='uid', db_column='uid', null=True)

Gives an error:

Field 'b' has column name 'uid' that is used by another field.
	HINT: Specify a 'db_column' for the field.

However, ForeignKey field is a ORM relation based on underlying column anyway.
I think it won't break anything if we allow different foreign keys to share same underlying column.
This adds more flexibility and will allow better django "on-boarding" process for legacy projects.
It will be also useful when A or B is proxy model - so we can get different proxy objects by different foreign keys referencing same DB row.

Another example can be found here:
https://stackoverflow.com/questions/36911804/django-use-same-column-for-two-foreign-keys

Change History (3)

comment:1 Changed 18 months ago by klass-ivan

If skip _check_column_name_clashes in models.base, the next issue will be in _do_insert - DB error that "Column '<column_name>' specified twice"

comment:2 Changed 18 months ago by Josh Smeaton

I'm struggling to see where the value for this change would be, and how common a situation this really is. I think the benefit of supporting this would be outweighed by users that are incorrectly duplicating keys on their models with copy/paste and running into legitimate issues.

Further, I believe you can (probably) get similar behaviour working if you reverse the location of your keys, and switch to using OneToOne. I haven't tested this myself, but I think this would work:

class A(Model):
    uid = CharField(unique=True)
    c = OneToOneField(to=C, to_field='uid', db_column='uid', null=True)

class B(Model):
    uid = CharField(unique=True)
    c = OneToOneField(to=C, to_field='uid', db_column='uid', null=True)

class C(Model):
   # other fields
   uid  = CharField(unique=False)

c = get_c(..)
c.a # fine
c.b # fine

comment:3 Changed 18 months ago by Tim Graham

Resolution: wontfix
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top