Commit 1ef4aeab authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #25078 -- Added support for disabled form fields

Thanks Keryn Knight and Tim Graham for the reviews.
parent 1fed8dd7
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ class Field(six.with_metaclass(RenameFieldMethods, object)):

    def __init__(self, required=True, widget=None, label=None, initial=None,
                 help_text='', error_messages=None, show_hidden_initial=False,
                 validators=[], localize=False, label_suffix=None):
                 validators=[], localize=False, disabled=False, label_suffix=None):
        # required -- Boolean that specifies whether the field is required.
        #             True by default.
        # widget -- A Widget class, or instance of a Widget class, that should
@@ -90,11 +90,14 @@ class Field(six.with_metaclass(RenameFieldMethods, object)):
        #                        hidden widget with initial value after widget.
        # validators -- List of additional validators to use
        # localize -- Boolean that specifies if the field should be localized.
        # disabled -- Boolean that specifies whether the field is disabled, that
        #             is its widget is shown in the form but not editable.
        # label_suffix -- Suffix to be added to the label. Overrides
        #                 form's label_suffix.
        self.required, self.label, self.initial = required, label, initial
        self.show_hidden_initial = show_hidden_initial
        self.help_text = help_text
        self.disabled = disabled
        self.label_suffix = label_suffix
        widget = widget or self.widget
        if isinstance(widget, type):
+6 −1
Original line number Diff line number Diff line
@@ -386,6 +386,9 @@ class BaseForm(object):
            # value_from_datadict() gets the data from the data dictionaries.
            # Each widget type knows how to retrieve its own data, because some
            # widgets split data over several HTML fields.
            if field.disabled:
                value = self.initial.get(name, field.initial)
            else:
                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
            try:
                if isinstance(field, FileField):
@@ -567,6 +570,8 @@ class BoundField(object):
            widget.is_localized = True

        attrs = attrs or {}
        if self.field.disabled:
            attrs['disabled'] = True
        auto_id = self.auto_id
        if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
            if not only_initial:
+11 −0
Original line number Diff line number Diff line
@@ -299,6 +299,17 @@ as the rendered output.
See the :ref:`format localization <format-localization>` documentation for
more information.

``disabled``
~~~~~~~~~~~~

.. attribute:: Field.disabled

.. versionadded:: 1.9

The ``disabled`` boolean argument, when set to ``True``, disables a form field
using the ``disabled`` HTML attribute so that it won't be editable by users.
Even if a user tampers with the field's value submitted to the server, it will
be ignored in favor of the value from the form's initial data.

Checking if the field data has changed
--------------------------------------
+3 −0
Original line number Diff line number Diff line
@@ -313,6 +313,9 @@ Forms
  and trailing whitespace.  As this defaults to ``True`` this is different
  behavior from previous releases.

* Form fields now support the :attr:`~django.forms.Field.disabled` argument,
  allowing the field widget to be displayed disabled by browsers.

Generic Views
^^^^^^^^^^^^^

+10 −0
Original line number Diff line number Diff line
@@ -176,6 +176,10 @@ class FieldsTests(SimpleTestCase):
        self.assertEqual(f.clean(' 1'), ' 1')
        self.assertEqual(f.clean('1 '), '1 ')

    def test_charfield_disabled(self):
        f = CharField(disabled=True)
        self.assertWidgetRendersTo(f, '<input type="text" name="f" id="id_f" disabled />')

    # IntegerField ################################################################

    def test_integerfield_1(self):
@@ -1076,6 +1080,12 @@ class FieldsTests(SimpleTestCase):
        form = ChoiceFieldForm()
        self.assertEqual([('P', 'Paul')], list(form.fields['choicefield'].choices))

    def test_choicefield_disabled(self):
        f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')], disabled=True)
        self.assertWidgetRendersTo(f,
            '<select id="id_f" name="f" disabled><option value="J">John</option>'
            '<option value="P">Paul</option></select>')

    # TypedChoiceField ############################################################
    # TypedChoiceField is just like ChoiceField, except that coerced types will
    # be returned:
Loading