Opened 6 years ago

Last modified 5 years ago

#29981 closed Bug

invalid_choice error when changing InlineModel with a OneToOne relation via to_field — at Initial Version

Reported by: Bernie Owned by: nobody
Component: contrib.admin Version: 2.1
Severity: Normal Keywords:
Cc: Sergey Fedoseev Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Code sample:

models.py:

from django.db import models

class Entry(models.Model):
    slug = models.SlugField(max_length=80, unique=True)
    title = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        verbose_name_plural = 'Entries'

class EntryDetail(models.Model):
    entry = models.OneToOneField(
        Entry,
        to_field='slug',
        primary_key=True,
        on_delete=models.CASCADE
    )
    description = models.TextField(blank=True, null=True)

class AnotherEntryDetail(models.Model):
    entry = models.OneToOneField(
        Entry,
        primary_key=True,
        on_delete=models.CASCADE
    )
    otherdescription = models.TextField(blank=True, null=True)

admin.py

from django.contrib import admin
from .models import Entry, EntryDetail, AnotherEntryDetail

class EntryDetailInline(admin.StackedInline):
    model = EntryDetail

class AnotherEntryDetailInline(admin.StackedInline):
    model = AnotherEntryDetail

@admin.register(Entry)
class EntryAdmin(admin.ModelAdmin):
    inlines = [
        EntryDetailInline,
        AnotherEntryDetailInline
    ]

    def get_readonly_fields(self, request, obj=None):
        # Even with EntryDetail.entry_id ON UPDATE: CASCADE set on DB-level
        # changing Entry.slug through the admin-change-form with EntryDetail-inline fails.
        # Set slug readonly as workaround. Don't know if this is worth fixing.
        readonly_fields = super().get_readonly_fields(request, obj)
        if hasattr(obj, 'entrydetail') and 'slug' not in readonly_fields:
            readonly_fields += ('slug',)
        return readonly_fields

Expected behavior:

In the admin:

  • add an Entry
  • fill slug and "Another entry detail" description
  • save
  • (change "Another entry detail" description)
  • save

Steps to reproduce the bug:

In the admin:

  • add an Entry
  • fill slug and "Entry detail" description
  • save
  • (change "Entry detail" description)
  • save
  • Error message in admin: "Please correct the error below."

Workaround:

in models.py replace

class EntryDetailInline(admin.StackedInline):
    model = EntryDetail

with:

from django.forms import BaseInlineFormSet

class EntryDetailFormSet(BaseInlineFormSet):
    def add_fields(self, form, index):
        super().add_fields(form, index)
        related_name = self._pk_field.remote_field.related_name or self._pk_field.remote_field.name
        if hasattr(self.instance, related_name):
            form.fields[self._pk_field.name].to_field = self._pk_field.remote_field.field_name

class EntryDetailInline(admin.StackedInline):
    model = EntryDetail
    formset = EntryDetailFormSet

Sorry for the confusing ticket-title, i couldn't come up with something better.

Change History (0)

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