Opened 5 days ago
Last modified 38 hours ago
#36295 assigned Bug
Unable to Override GenericForeignKey in Inherited Abstract Class
Description ¶
Attempting to override a GenericForeignKey field in an inherited abstract model does not work as expected. According to the Django documentation, it should be possible to hide a field inherited from an abstract model by setting it to None
.
However, this does not seem to work for GenericForeignKey.
I have created a Django project for quick testing.
Steps to replicate:
- Define an abstract model with a GenericForeignKey field.
- Create another abstract model that inherits from the first and attempt to override the GenericForeignKey field by setting it to None.
- Define a concrete model that inherits from the second abstract model.
Code Example
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models class AbstractBaseModel(models.Model): content_type = models.ForeignKey( ContentType, on_delete=models.SET_NULL, null=True, blank=True ) object_id = models.PositiveIntegerField(null=True, blank=True) related_object = GenericForeignKey("content_type", "object_id") description = models.TextField(null=True, blank=True) class Meta: abstract = True class AbstractDerivedModel(AbstractBaseModel): related_object = None # Override GenericForeignKey description = None class Meta: abstract = True class ConcreteEntity(AbstractDerivedModel): name = models.CharField(max_length=255) class Meta: abstract = False
Expected Behavior:
The related_object field
in AbstractDerivedModel
should override the GenericForeignKey
in AbstractBaseModel
, making it effectively absent in ConcreteEntity
.
Actual Behavior:
Django still considers the GenericForeignKey field from AbstractBaseModel when defining ConcreteEntity, leading to unexpected behavior.
Additional Notes:
- Overriding standard model fields with
None
works as expected, butGenericForeignKey
does not follow the same behavior (description
field in the above example). - There is no explicit mention in the documentation that GenericForeignKey is exempt from the field-hiding mechanism. I checked the following pages:
According to the ticket's flags, the next step(s) to move this issue forward are:
- To provide a patch by sending a pull request. Claim the ticket when you start working so that someone else doesn't duplicate effort. Before sending a pull request, review your work against the patch review checklist. Check the "Has patch" flag on the ticket after sending a pull request and include a link to the pull request in the ticket comment when making that update. The usual format is:
[https://github.com/django/django/pull/#### PR]
.
Change History (5)
comment:1 by , 5 days ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 5 days ago
Component: | Database layer (models, ORM) → contrib.contenttypes |
---|
comment:3 by , 5 days ago
Hello Sarah! Can I get some pointers how can I approach to solve this issue? I would like to attempt a fix.
comment:4 by , 4 days ago
[Ignore this fix, unit tests were failing. My bad, for rushing it]
This is my first time working with the Django source code. After reviewing the codebase, I believe the fix below might address the issue. However, I'm unsure whether this is the expected behavior that requires a documentation update or if it's an actual bug.
File db/models/base.py -- line 348
if field.column is not None: # the exact fix field = copy.deepcopy(field) if not base._meta.abstract: field.mti_inherited = True new_class.add_to_class(field.name, field)
Apologies, but I'm unsure how to present this from the codebase. It would be helpful if someone could guide me on how to share the diff, similar to the comments above. Thanks!
comment:5 by , 38 hours ago
Owner: | set to |
---|---|
Status: | new → assigned |
Thank you!
Using the models as defined above, I was able to replicate
TabularUnified tests/generic_relations/tests.py