Browse Source

Fixed #28937 -- Allowed BinaryField to be editable=True.

Cameron Curry 7 years ago
parent
commit
622ead6aaf

+ 1 - 0
AUTHORS

@@ -138,6 +138,7 @@ answer newbie questions, and generally made Django that much better:
     btoll@bestweb.net
     C8E
     Calvin Spealman <ironfroggy@gmail.com>
+    Cameron Curry
     Cameron Knight (ckknight)
     Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
     Carl Meyer <carl@oddbird.net>

+ 5 - 2
django/db/models/fields/__init__.py

@@ -2295,14 +2295,17 @@ class BinaryField(Field):
     empty_values = [None, b'']
 
     def __init__(self, *args, **kwargs):
-        kwargs['editable'] = False
+        kwargs.setdefault('editable', False)
         super().__init__(*args, **kwargs)
         if self.max_length is not None:
             self.validators.append(validators.MaxLengthValidator(self.max_length))
 
     def deconstruct(self):
         name, path, args, kwargs = super().deconstruct()
-        del kwargs['editable']
+        if self.editable:
+            kwargs['editable'] = True
+        else:
+            del kwargs['editable']
         return name, path, args, kwargs
 
     def get_internal_type(self):

+ 8 - 2
docs/ref/models/fields.txt

@@ -420,8 +420,14 @@ 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. It is also not possible to
-include a ``BinaryField`` in a :class:`~django.forms.ModelForm`.
+to filter a queryset on a ``BinaryField`` value.
+
+By default, ``BinaryField`` sets :attr:`~Field.editable` to ``False``, in which
+case it can't be included in a :class:`~django.forms.ModelForm`.
+
+.. versionchanged:: 2.1
+
+    Older versions don't allow setting ``editable`` to ``True``.
 
 .. admonition:: Abusing ``BinaryField``
 

+ 3 - 0
docs/releases/2.1.txt

@@ -157,6 +157,9 @@ Models
 
 * Models can now use ``__init_subclass__()`` from :pep:`487`.
 
+* A ``BinaryField`` may now be set to ``editable=True`` if you wish to include
+  it in model forms.
+
 Requests and Responses
 ~~~~~~~~~~~~~~~~~~~~~~
 

+ 5 - 0
docs/topics/forms/modelforms.txt

@@ -62,6 +62,11 @@ Model field                         Form field
                                     ``min_value`` set to -9223372036854775808
                                     and ``max_value`` set to 9223372036854775807.
 
+:class:`BinaryField`                :class:`~django.forms.CharField`, if
+                                    :attr:`~.Field.editable` is set to
+                                    ``True`` on the model field, otherwise not
+                                    represented in the form.
+
 :class:`BooleanField`               :class:`~django.forms.BooleanField`
 
 :class:`CharField`                  :class:`~django.forms.CharField` with

+ 4 - 0
tests/field_deconstruction/tests.py

@@ -514,3 +514,7 @@ class FieldDeconstructionTests(SimpleTestCase):
         self.assertEqual(path, "django.db.models.BinaryField")
         self.assertEqual(args, [])
         self.assertEqual(kwargs, {})
+        field = models.BinaryField(editable=True)
+        name, path, args, kwargs = field.deconstruct()
+        self.assertEqual(args, [])
+        self.assertEqual(kwargs, {'editable': True})

+ 9 - 0
tests/model_fields/test_binaryfield.py

@@ -1,4 +1,5 @@
 from django.core.exceptions import ValidationError
+from django.db import models
 from django.test import TestCase
 
 from .models import DataModel
@@ -25,3 +26,11 @@ class BinaryFieldTests(TestCase):
         dm = DataModel(short_data=self.binary_data * 4)
         with self.assertRaises(ValidationError):
             dm.full_clean()
+
+    def test_editable(self):
+        field = models.BinaryField()
+        self.assertIs(field.editable, False)
+        field = models.BinaryField(editable=True)
+        self.assertIs(field.editable, True)
+        field = models.BinaryField(editable=False)
+        self.assertIs(field.editable, False)