Code

Opened 6 years ago

Last modified 3 months ago

#9373 new Bug

"This field is required" error even on empty inlines formsets in the admin model page, when hiding a choice field of a custom form.

Reported by: tyrion.mx@… Owned by: nobody
Component: Forms Version: 1.7-alpha-1
Severity: Normal Keywords: admin, inlines
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have a custom Form for one of my models (in the example SecondModel) that adds one choice field with an initial value.
If I use that model/form as an inline formset and I exclude the extra field using the "fields" attribute of the ModelAdmin, I got "This Field is required" on all the forms of the formset, including those who where left blank. Here a simple example:

# models.py
from django.db import models

class FirstModel(models.Model):
    a = models.CharField(max_length=10)
    b = models.CharField(max_length=10)

class SecondModel(models.Model):
    link = models.ForeignKey(FirstModel)
    c = models.CharField(max_length=10)

# admin.py
from django.contrib import admin
from bug.bugged import models, forms

class SecondAdmin(admin.TabularInline):
    model = models.SecondModel
    form = forms.SecondForm
    fields = ['c']
    extra = 3

class FirstAdmin(admin.ModelAdmin):
    inlines = [SecondAdmin]
 
admin.site.register(models.FirstModel, FirstAdmin)

# forms.py
from django import forms
from bug.bugged import models

DUMMY_CHOICES = (
    (0, 'a'),
    (1, 'b'),
    (2, 'c')
)

class SecondForm(forms.ModelForm):
    d = forms.IntegerField(label='d', initial=0, widget=forms.Select(choices=DUMMY_CHOICES))
    class Meta:
        model = models.SecondModel

The problem is fields = ['c'], commenting out that line I get no errors.
I guess, this is beacuse of the has_changed check, called by the full_clean method of forms.Form. It happens that changed_data compares the initial "d" value that had been set to 0 with the result of "field.widget.value_from_datadict(self.data,..." that is None because we have not a key for "d" in self.data. So changed_data will contain "d" even if the form has not been changed.

From django/forms/forms.py

                prefixed_name = self.add_prefix(name)
                data_value = field.widget.value_from_datadict(self.data, self.files, prefixed_name)
                if not field.show_hidden_initial:
                    initial_value = self.initial.get(name, field.initial)

Attachments (0)

Change History (5)

comment:1 Changed 5 years ago by jacob

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 3 years ago by lukeplant

  • Severity set to Normal
  • Type set to Bug

comment:3 Changed 2 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:4 Changed 2 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:5 Changed 3 months ago by Siecje

  • Keywords admin, inlines added
  • Version changed from 1.0 to 1.7-alpha-1

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as new
The owner will be changed from nobody to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.