Opened 6 years ago

Closed 6 years ago

#10108 closed (wontfix)

Two classes with a common superclass have multiple ForeignKeys from one to the other if the one has a single Foreign Key to the other.

Reported by: mail@… Owned by: nobody
Component: Core (Other) Version: master
Severity: Keywords: foreign key, inheritance, ForeignKey, OneToOne
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description (last modified by kmtracey)

Given three classes as follows:

class Item(models.Model):

class Computer(Item):

class CPU(Item):
    computer = models.ForeignKey(Computer)

When inlining CPU into Computer in the admin interface the following exception is raised:

<class 'comprec.inventory.models.CPU'> has more than 1 ForeignKey to <class 'comprec.inventory.models.Computer'>

This is caused by the OneToOne field created implicitly by the inheritance as mentioned on http://docs.djangoproject.com/en/dev/ref/models/fields/#onetoonefield conflicting with the defined ForeignKey on the model. This leads to unexpected behaviour as it is expected that the single defined ForeignKey field is used in the admin form. The error appears to be caused by the _get_foreign_key function in forms/models.py which uses isinstance(f, ForeignKey) on the fields on the model with the ForeignKey to find which field to use but this returns true on OneToOne fields, not just ForeignKey fields.

A traceback of the error is available at http://dpaste.com/112033/.

Change History (2)

comment:1 Changed 6 years ago by kmtracey

  • Description modified (diff)
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I believe you can set up admin inlines for items related by OneToOne (though you're limited to one in the inline "list"), so I don't think we can change the function you mention to simply not consider OneToOnes candidates. Maybe the auto-added OneToOnes that come with inheritance, but the combination of inheritance and inlines in the admin makes my head spin (not helped by the fact that it is late night here), so input from someone who better understands admin, inheritance, and inlines and how they all fit together would help. I'm not sure it would make sense to always disallow the auto-added OneToOne as being the parent link for an inline model?

If not and in the meantime even if so, you can specify an fk_name (http://docs.djangoproject.com/en/dev/ref/contrib/admin/#fk-name) for your inline model admin:

class CPUInline(admin.TabularInline):
    model = CPU
    fk_name = 'computer'

That will tell the admin which ForeignKey to use for the parent link. And then you will need the patch on #10075 to fix the Cannot assign None: "CPU.item_ptr" does not allow null values error you will get if you try to save a computer with a newly-added inline CPU.

comment:2 Changed 6 years ago by jacob

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

Karen's correct: a OneToOneField is a ForeignKey, and we can't ignore one of 'em automatically. fk_name exists precisely for this purpose.

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