Added support for serializing BinaryField
This commit is contained in:
parent
8ee1eddb7e
commit
d680a3f447
|
@ -6,6 +6,7 @@ import datetime
|
||||||
import decimal
|
import decimal
|
||||||
import math
|
import math
|
||||||
import warnings
|
import warnings
|
||||||
|
from base64 import b64decode, b64encode
|
||||||
from itertools import tee
|
from itertools import tee
|
||||||
|
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
|
@ -19,7 +20,7 @@ from django.utils.functional import curry, total_ordering
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.encoding import smart_text, force_text
|
from django.utils.encoding import smart_text, force_text, force_bytes
|
||||||
from django.utils.ipv6 import clean_ipv6_address
|
from django.utils.ipv6 import clean_ipv6_address
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
|
@ -1318,3 +1319,13 @@ class BinaryField(Field):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
return connection.Database.Binary(value)
|
return connection.Database.Binary(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def value_to_string(self, obj):
|
||||||
|
"""Binary data is serialized as base64"""
|
||||||
|
return b64encode(force_bytes(self._get_val_from_obj(obj))).decode('ascii')
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
# If it's a string, it should be base64-encoded data
|
||||||
|
if isinstance(value, six.text_type):
|
||||||
|
return six.memoryview(b64decode(force_bytes(value)))
|
||||||
|
return value
|
||||||
|
|
|
@ -142,6 +142,8 @@ def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||||
|
|
||||||
If strings_only is True, don't convert (some) non-string-like objects.
|
If strings_only is True, don't convert (some) non-string-like objects.
|
||||||
"""
|
"""
|
||||||
|
if isinstance(s, six.memoryview):
|
||||||
|
s = bytes(s)
|
||||||
if isinstance(s, bytes):
|
if isinstance(s, bytes):
|
||||||
if encoding == 'utf-8':
|
if encoding == 'utf-8':
|
||||||
return s
|
return s
|
||||||
|
|
|
@ -12,6 +12,9 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
# The following classes are for testing basic data
|
# The following classes are for testing basic data
|
||||||
# marshalling, including NULL values, where allowed.
|
# marshalling, including NULL values, where allowed.
|
||||||
|
|
||||||
|
class BinaryData(models.Model):
|
||||||
|
data = models.BinaryField(null=True)
|
||||||
|
|
||||||
class BooleanData(models.Model):
|
class BooleanData(models.Model):
|
||||||
data = models.BooleanField()
|
data = models.BooleanField()
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,11 @@ from django.db import connection, models
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
from django.utils.unittest import skipUnless
|
from django.utils.unittest import skipUnless
|
||||||
|
|
||||||
from .models import (BooleanData, CharData, DateData, DateTimeData, EmailData,
|
from .models import (BinaryData, BooleanData, CharData, DateData, DateTimeData, EmailData,
|
||||||
FileData, FilePathData, DecimalData, FloatData, IntegerData, IPAddressData,
|
FileData, FilePathData, DecimalData, FloatData, IntegerData, IPAddressData,
|
||||||
GenericIPAddressData, NullBooleanData, PositiveIntegerData,
|
GenericIPAddressData, NullBooleanData, PositiveIntegerData,
|
||||||
PositiveSmallIntegerData, SlugData, SmallData, TextData, TimeData,
|
PositiveSmallIntegerData, SlugData, SmallData, TextData, TimeData,
|
||||||
|
@ -116,10 +117,17 @@ def inherited_create(pk, klass, data):
|
||||||
# test data objects of various kinds
|
# test data objects of various kinds
|
||||||
def data_compare(testcase, pk, klass, data):
|
def data_compare(testcase, pk, klass, data):
|
||||||
instance = klass.objects.get(id=pk)
|
instance = klass.objects.get(id=pk)
|
||||||
testcase.assertEqual(data, instance.data,
|
if klass == BinaryData and data is not None:
|
||||||
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (
|
testcase.assertEqual(bytes(data), bytes(instance.data),
|
||||||
pk, data, type(data), instance.data, type(instance.data))
|
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (
|
||||||
)
|
pk, repr(bytes(data)), type(data), repr(bytes(instance.data)),
|
||||||
|
type(instance.data))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
testcase.assertEqual(data, instance.data,
|
||||||
|
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (
|
||||||
|
pk, data, type(data), instance, type(instance.data))
|
||||||
|
)
|
||||||
|
|
||||||
def generic_compare(testcase, pk, klass, data):
|
def generic_compare(testcase, pk, klass, data):
|
||||||
instance = klass.objects.get(id=pk)
|
instance = klass.objects.get(id=pk)
|
||||||
|
@ -175,8 +183,10 @@ inherited_obj = (inherited_create, inherited_compare)
|
||||||
|
|
||||||
test_data = [
|
test_data = [
|
||||||
# Format: (data type, PK value, Model Class, data)
|
# Format: (data type, PK value, Model Class, data)
|
||||||
(data_obj, 1, BooleanData, True),
|
(data_obj, 1, BinaryData, six.memoryview(b"\x05\xFD\x00")),
|
||||||
(data_obj, 2, BooleanData, False),
|
(data_obj, 2, BinaryData, None),
|
||||||
|
(data_obj, 5, BooleanData, True),
|
||||||
|
(data_obj, 6, BooleanData, False),
|
||||||
(data_obj, 10, CharData, "Test Char Data"),
|
(data_obj, 10, CharData, "Test Char Data"),
|
||||||
(data_obj, 11, CharData, ""),
|
(data_obj, 11, CharData, ""),
|
||||||
(data_obj, 12, CharData, "None"),
|
(data_obj, 12, CharData, "None"),
|
||||||
|
|
Loading…
Reference in New Issue