#29981: "Please correct the error below." (with no errors displayed) when 
changing
an inline that has a one-to-one relation to the parent that uses to_field
-------------------------------+------------------------------------
     Reporter:  Bernie         |                    Owner:  nobody
         Type:  Bug            |                   Status:  new
    Component:  contrib.admin  |                  Version:  2.1
     Severity:  Normal         |               Resolution:
     Keywords:                 |             Triage Stage:  Accepted
    Has patch:  0              |      Needs documentation:  0
  Needs tests:  0              |  Patch needs improvement:  0
Easy pickings:  0              |                    UI/UX:  0
-------------------------------+------------------------------------
Changes (by Tim Graham):

 * stage:  Unreviewed => Accepted


Old 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.''

New 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 EntryDetail(models.Model):
     entry = models.OneToOneField(
         Entry,
         to_field='slug',
         primary_key=True,
         on_delete=models.CASCADE
     )
     description = models.TextField(blank=True, null=True)
 }}}

 admin.py

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

 class EntryDetailInline(admin.StackedInline):
     model = EntryDetail

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

     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
 }}}

 **Steps to reproduce the bug:**

 In the admin:
 * add an Entry
 * fill slug, title, and "Entry detail" description
 * save and continue editing
 * change "Entry detail" description
 * save
 * Error message in admin: "Please correct the error below." (with no
 errors listed). `formset[0].errors` is `[{'entry': ['The inline value did
 not match the parent instance.']}]` which comes from
 `InlineForeignKeyField` value is `aaa` and `orig` is `1`.

 **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
 }}}

--

Comment:

 I reproduced the issue on master
 (78fc64578a8715b9812075bbebc829c1251c07fa). I removed
 `AnotherEntryDetailInline` from the description as it doesn't seem
 required to reproduce the issue.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29981#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/066.70c218da030435ae5cdfabb769c08b91%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to