Django自定义字段:只对DB上的值运行to_python()? [英] Django Custom Field: Only run to_python() on values from DB?
问题描述
如果在DB中加载了该字段中的数据,那么我如何才能确定自定义字段的* to_python()*方法?
我试图使用自定义字段来处理单个模型属性的Base64编码/解码。一切似乎正常工作,直到我实例化了一个新的模型实例,并使用它的明文值设置这个属性...在这一点上,Django试图解码该字段,但是由于它是纯文本而失败。
I'm trying to use a Custom Field to handle the Base64 Encoding/Decoding of a single model property. Everything appeared to be working correctly until I instantiated a new instance of the model and set this property with its plaintext value...at that point, Django tried to decode the field but failed because it was plaintext.
自定义字段实现的魅力在于我以为我可以处理100%的编码/解码逻辑,因此我的代码中没有其他部分需要知道它。我做错了什么?
The allure of the Custom Field implementation was that I thought I could handle 100% of the encoding/decoding logic there, so that no other part of my code ever needed to know about it. What am I doing wrong?
(注:这只是一个例子来说明我的问题,我不需要关于我应该怎么做或不应该的建议使用Base64 Encoding)
def encode(value):
return base64.b64encode(value)
def decode(value):
return base64.b64decode(value)
class EncodedField(models.CharField):
__metaclass__ = models.SubfieldBase
def __init__(self, max_length, *args, **kwargs):
super(EncodedField, self).__init__(*args, **kwargs)
def get_prep_value(self, value):
return encode(value)
def to_python(self, value):
return decode(value)
class Person(models.Model):
internal_id = EncodedField(max_length=32)
...当我在交互式shell中这样做时,它会中断。为什么在这里调用to_python()?
...and it breaks when I do this in the interactive shell. Why is it calling to_python() here?
>>> from myapp.models import *
>>> Person(internal_id="foo")
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py", line 330, in __init__
setattr(self, field.attname, val)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/subclassing.py", line 98, in __set__
obj.__dict__[self.field.name] = self.field.to_python(value)
File "../myapp/models.py", line 87, in to_python
return decode(value)
File "../myapp/models.py", line 74, in decode
return base64.b64decode(value)
File "/usr/lib/python2.6/base64.py", line 76, in b64decode
raise TypeError(msg)
TypeError: Incorrect padding
将能够做这样的事情...
I had expected I would be able to do something like this...
>>> from myapp.models import *
>>> obj = Person(internal_id="foo")
>>> obj.internal_id
'foo'
>>> obj.save()
>>> newObj = Person.objects.get(internal_id="foo")
>>> newObj.internal_id
'foo'
>>> newObj.internal_id = "bar"
>>> newObj.internal_id
'bar'
>>> newObj.save()
...我做错了什么?
推荐答案
当您首次分配值时,您只能获得 TypeError
到现场?你可以写一个try / except在它周围:
Do you only get the TypeError
when you first assign a value to the field? You could just write a try/except around it:
def to_python(self, value):
try:
return decode(value)
except TypeError:
return value
这不是最干净的解决方案,但您可以尝试一下,看看是否让您按照您期望的方式与现场合作。
It's not the cleanest solution, but you could try that and see if it lets you work with the field the way you're expecting to.
这篇关于Django自定义字段:只对DB上的值运行to_python()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!