I have a model with self relation in models.py:
from uuid import uuid4 from django.db
import models
class Example(models.Model):
uid = models.UUIDField(primary_key=True, default=uuid4)
title = models.CharField(max_length=128)
parent = models.ForeignKey("self", related_name="subexamples", blank=True, null=True)
and Django admin models:
from .models import Example
from django.contrib import admin
class ExampleInline(admin.TabularInline):
model = Example
exclude = ("uid",)
extra = 1
verbose_name = "Subexample"
show_change_link = True
class ExampleAdmin(admin.ModelAdmin):
search_fields = ("title", )
exclude = ("uid",)
inlines = [ExampleInline,]
admin.site.register(Example, ExampleAdmin)
On the admin site I can see the main model and inline like in any other cases. The problem start after adding first Inline object. After it's added I can no longer delete or change it. The only mistake I see is "Please correct the error below." without any problems below. Also no any problems in Django logs. I'm using Django==5.0.2
After reading about similar problems I found that customized PK breaks logic but actually didn't find any workarounds for this problem.
It seems that Django's inline forms don't handle exclude
nicely for primary keys. I managed to replicate the behavior.
But, the good news is, we can resolve this issue, by marking the primary key as editable=False
[Django-doc], which actually means that these fields are not editable in a ModelForm
, or at least not without explicitly adding it. This makes sense for a UUIDField
that is a primary key, since you let the system define the UUID, not the user: this was also (I think), the reason you picked exclude = ('uid',)
. For some reason that does not work very well, but we can just do this in the model layer:
class Example(models.Model):
uid = models.UUIDField(primary_key=True, default=uuid4, editable=False)
title = models.CharField(max_length=128)
parent = models.ForeignKey(
'self', related_name='subexamples', blank=True, null=True
)
Update: I have added a ticket [Django-ticket] and created a opened a pull request [GitHub] to resolve this.