Non-editable error for a GenericForeignKey in an ModelForm when updating to version 5.1

I have a field in a model form as GenericForeignKey, and it was woriking fine in version 5.0.9, however; after updating to 5.1 I get an exception:

django.core.exceptions.FieldError: 'my_generic_foreign_model' cannot be specified for my_model_form model form as it is a non-editable field

Before it was parsing only the model and object_id:

<django.db.models.fields.related.ForeignKey: my_generic_foreign_model_model>
<django.db.models.fields.PositiveIntegerField: my_generic_foreign_model_object_id>

now in addition, it parses the as whole:
<django.contrib.contenttypes.fields.GenericForeignKey: my_generic_foreign_model>

Thanks in advanced

Hi, please post your model code

I ran into the same issue, it appears when you have a model form with a field that is the same name as in the model (in this case a GFK) it takes the read-only from the model field instead of the form field. This used to work fine in Django 5.0 and earlier but broke in 5.1. For example we have:

class EventRule():
    ...
    action_object_type = models.ForeignKey(
        to='contenttypes.ContentType',
        related_name='eventrule_actions',
        on_delete=models.CASCADE
    )
    action_object_id = models.PositiveBigIntegerField(
        blank=True,
        null=True
    )
    action_object = GenericForeignKey(
        ct_field='action_object_type',
        fk_field='action_object_id'
    )

Then in the form:

class EventRuleForm():
    ...
    action_object = forms.CharField(
        label=_('Action object'),
        required=True,
        help_text=_('Webhook name or script as dotted path module.Class')
    )

In this case we handle action_object in the clean method and use it to set instance.action_object. But now in Django 5.1 it throws the django.core.exceptions.FieldError shown above.

Not sure if this is an undocumented change on purpose or a bug. Will look at getting a smaller repro scenario together.

I ran into this as well. Looks like it might be caused by refactoring GFK to inherit from the base Field class. As part of the migration in Fixed #35224 -- Made GenericForeignKey inherit from Field. · django/django@6002df0 · GitHub, the self.editable is hardcoded to False. Hard to tell if it was intentional, but my guess given this used to work fine is that it was an oversight leading to accidental breaking change.

class GenericForeignKey(FieldCacheMixin, Field):
    def __init__(
        self, ct_field="content_type", fk_field="object_id", for_concrete_model=True
    ):
        super().__init__(editable=False)

As a quick workaround, I have:

from django.contrib.contenttypes.fields import GenericForeignKey

class EditableGenericForeignKey(GenericForeignKey):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.editable = True

And then updated my Models to use EditableGenericForeignKey instead.

class Foo(models.Model):
    owner = EditableGenericForeignKey('owner_content_type', 'owner_id')

The form can then be used unchanged from previous Django versions in the admin site.

Seems to work.

1 Like