Opened 5 years ago

Closed 5 years ago

#29947 closed Bug (wontfix)

Inlines containing a field with default value are considered empty and not saved

Reported by: ksl Owned by: nobody
Component: contrib.admin Version: 2.1
Severity: Normal Keywords: inline default
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Abstract

Bug is located in the admin app, in the change form of a model. It prevents adding an inline object when the inline contains only fields with their default values.

Steps to reproduce

  • Using the tutorial's project, with the following modifications :
# models.py
from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)


class Choice(models.Model):
    CHOICE_ANSWER = (("y", "Yes"),
                     ("n", "No"),
                     ("m", "Maybe"),
                     )

    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    answer = models.CharField("answer", max_length=2, choices=CHOICE_ANSWER, default="y")

# admin.py
from django.contrib import admin

from .models import Choice, Question


class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 0


class QuestionAdmin(admin.ModelAdmin):
    inlines = [ChoiceInline]


admin.site.register(Question, QuestionAdmin)
  • In the admin, create a new question object
  • Add a new choice inline
  • Leave choice's default value ("Yes")
  • Save the question object

Result

The question object is saved without its choice inline.

Expected result

The choice inline of the created question object should be saved, no matter its value (default or not).

Versions affected

At least 2.0.2, 2.1.2 and 2.1.3.

Change History (6)

comment:1 by Tim Graham, 5 years ago

The behavior stems from the fact that forms aren't saved unless the user has changed them. I'm not sure how we could change behavior for this edge case while maintaining backwards compatibility. Do you have a suggestion?

comment:2 by ksl, 5 years ago

I understand that forms undergo some processing to decide whether they have been changed and therefore need to be saved.

The point here is that a field with its default value should be considered a "sane" (changed, if you will) input, and not an empty input. Don't you agree? Is that technically feasible?

comment:3 by Tim Graham, 5 years ago

Considering fields with defaults as "changed" would be backwards incompatible. Consider a set of three initial inline forms that include a default field. The user fills in the fields of the first form but doesn't touch the other two. The first form is considered changed while the second two are unchanged and ignored while saving. If defaults are treated as changed fields, all three forms would be considered "changed" and the user couldn't save the page without filling out all three of the forms.

comment:4 by ksl, 5 years ago

I see your point now. It then all boils down to the meaning of a field's default.

I always thought of "default" as a way for my users to be provided with a sensible default (hey!) value so that they are not forced to pick that value in a select (for instance). On the other hand, what you are describing is a "default" that almost behaves as a "blank value".

Since having blank=False along with a default value for a given field does not lead to the desired result (ie: the field being saved with its default value) and that changing that would be backwards-incompatible, may I propose an additional boolean flag (save_default?) on Field, as follows?

age = models.PositiveSmallIntegerField(_("age"), blank=False, null=False, default=0, save_default=True)

If not doable, maybe some list borne by the ModelAdmin: save_defaults = [age]?

comment:5 by Tim Graham, 5 years ago

I don't think the use case (a form with all of its fields having defaults) is common enough to warrant a change in Django. Probably this problem could be solved with a custom form (override Form.has_changed() to return True, perhaps).

comment:6 by Simon Charette, 5 years ago

Resolution: wontfix
Status: newclosed

I agree with Tim's backward compatibility concerns regarding has changed detection based off initial_data .

Thank you for report but given this is an uncommon use case that can be worked around by overriding Form.has_changed or changed_data I'll close this ticket as wontfix.

You can bring the discussion on the developer list to attempt to achieve a different consensus if you disagree with the resolution here.

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