Commit d43156e1 authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #26238 -- Raised explicit error for non-editable field in ModelForm

Thanks Luke Crouch for the report and Simon Charette for the review.
parent 6670da75
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -148,6 +148,12 @@ def fields_for_model(model, fields=None, exclude=None, widgets=None,
                               if isinstance(f, ModelField)]
    for f in sorted(chain(opts.concrete_fields, sortable_virtual_fields, opts.many_to_many)):
        if not getattr(f, 'editable', False):
            if (fields is not None and f.name in fields and
                    (exclude is None or f.name not in exclude)):
                raise FieldError(
                    "'%s' cannot be specified for %s model form as it is a non-editable field" % (
                        f.name, model.__name__)
                )
            continue
        if fields is not None and f.name not in fields:
            continue
+2 −1
Original line number Diff line number Diff line
@@ -415,7 +415,8 @@ guaranteed to fit numbers from ``-9223372036854775808`` to

A field to store raw binary data. It only supports ``bytes`` assignment. Be
aware that this field has limited functionality. For example, it is not possible
to filter a queryset on a ``BinaryField`` value.
to filter a queryset on a ``BinaryField`` value. It is also not possible to
include a ``BinaryField`` in a :class:`~django.forms.ModelForm`.

.. admonition:: Abusing ``BinaryField``

+15 −0
Original line number Diff line number Diff line
@@ -2282,6 +2282,21 @@ class ModelOtherFieldTests(SimpleTestCase):
        self.assertTrue(HomepageForm({'url': 'http://www.example.com:8000/test'}).is_valid())
        self.assertTrue(HomepageForm({'url': 'http://example.com/foo/bar'}).is_valid())

    def test_modelform_non_editable_field(self):
        """
        When explicitely including a non-editable field in a ModelForm, the
        error message should be explicit.
        """
        # 'created', non-editable, is excluded by default
        self.assertNotIn('created', ArticleForm().fields)

        msg = "'created' cannot be specified for Article model form as it is a non-editable field"
        with self.assertRaisesMessage(FieldError, msg):
            class InvalidArticleForm(forms.ModelForm):
                class Meta:
                    model = Article
                    fields = ('headline', 'created')

    def test_http_prefixing(self):
        """
        If the http:// prefix is omitted on form input, the field adds it again. (Refs #13613)