Opened 11 years ago
Closed 10 years ago
#22850 closed Uncategorized (invalid)
False reverse accessor clash with inherited classes
Reported by: | Ilya Semenov | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Consider the following models.py
:
class Base(models.Model): field1 = models.IntegerField() class Derived(Base): field2 = models.IntegerField() class Pointer(models.Model): base = models.ForeignKey(Base) derived = models.ForeignKey(Derived)
it crashes:
Unhandled exception in thread started by <function wrapper at 0x105daab90> Traceback (most recent call last): File "/Users/semenov/work/project/venv/src/django/django/utils/autoreload.py", line 170, in wrapper fn(*args, **kwargs) File "/Users/semenov/work/project/venv/src/django/django/core/management/commands/runserver.py", line 104, in inner_run self.validate(display_num_errors=True) File "/Users/semenov/work/project/venv/src/django/django/core/management/base.py", line 361, in validate return self.check(app_configs=app_configs, display_num_errors=display_num_errors) File "/Users/semenov/work/project/venv/src/django/django/core/management/base.py", line 413, in check raise CommandError(msg) django.core.management.base.CommandError: System check identified some issues: ERRORS: project.Pointer.derived: (fields.E304) Reverse accessor for 'Pointer.derived' clashes with reverse accessor for 'Pointer.base'. HINT: Add or change a related_name argument to the definition for 'Pointer.derived' or 'Pointer.base'.
However, if I rewrite it to the semantically equivalent form:
class AbstractBase(models.Model): field1 = models.IntegerField() class Meta: abstract = True class Base(AbstractBase): pass class Derived(AbstractBase): field2 = models.IntegerField() class Pointer(models.Model): base = models.ForeignKey(Base) derived = models.ForeignKey(Derived)
it works fine.
EXPECTED RESULT: both cases should work identically (create identical database tables and ORM accessors).
Change History (3)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Version: | 1.7-beta-2 → 1.4 |
---|
I tested both cases on Django 1.4.X branch, the first version crashed with similar error:
Unhandled exception in thread started by <bound method Command.inner_run of <django.core.management.commands.runserver.Command object at 0x101e3b110>> Traceback (most recent call last): File "/Users/semenov/work/project/venv/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 91, in inner_run self.validate(display_num_errors=True) File "/Users/semenov/work/project/venv/lib/python2.7/site-packages/django/core/management/base.py", line 270, 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: project.pointer: Accessor for field 'derived' clashes with related field 'Derived.pointer_set'. Add a related_name argument to the definition for 'derived'.
The second version worked fine.
comment:3 by , 10 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
The two forms are really not equivalent -- they will created different database tables. An explanation of the differences is here.
Having a ForeignKey to both Base and Derived in the first example in really redundant as they will refer to the same database column (Base.id
). I believe that's the reason for the validation error.
Did the first version work in older versions of Django?