我用以下代码编写了一个简短的单元测试:
my_object = MyObject()
my_object.data = b'12345'
my_object.save()
saved_object = MyObject.objects.first()
assert saved_object.data == my_object.data
其中MyObject
定义为:
class MyObject(models.Model):
data = models.BinaryField(default=None)
我希望断言传递,因为我只是保存一些字节数据然后检索它。但是,我最终得到了:
AssertionError: assert <memory at 0x10e2abc48> == b'12345'
我猜这与直接将字节串保存到二进制字段有关。另一方面,保存成功后似乎很奇怪。而且我有点难以找到Django的BinaryField
的一些很好的例子用法。任何人都可以向我解释这里发生了什么或者我做错了什么?非常感谢。
答案 0 :(得分:4)
Django将BinaryField
的内容规范化为缓冲区。在Python2中,Python3中的buffer
和memoryview
是特定的。
您可以在源代码中看到:
在Python2 buffer
中没有实现比较逻辑,这就是你的断言失败的原因:
Python 2.7.11
>>> m = buffer(b'hello')
>>> m == b'hello'
False
>>> bytes(m) == b'hello'
True
然而,它确实实现了切片和长度等其他操作:
>>> len(m)
5
>>> m[1:]
'ello'
在Python 3中,故事要好得多,因为它实现了所有预期的操作:
Python 3.5.1
>>> m = memoryview(b'hello')
>>> m
<memory at 0x109e8b108>
>>> bytes(m)
b'hello'
>>> m == b'hello'
True
>>> bytes(m) == b'hello'
True
>>> len(m)
5
>>> m[1:]
<memory at 0x109e8b1c8>
我不确定Django之所以这样做,但我的猜测是效率。缓冲区在处理内存方面效率更高。例如,当您进行切片时,它可以重用相同的内存,而不是分配更多的内存。