summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/forms/models.py6
-rw-r--r--docs/ref/models/fields.txt3
-rw-r--r--tests/model_forms/tests.py15
3 files changed, 23 insertions, 1 deletions
diff --git a/django/forms/models.py b/django/forms/models.py
index 8e8c8cfb55..be9e63d144 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -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
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index 4a1c9eefbb..de493dda67 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -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``
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 968407e845..a2e7c66419 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -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)