Django自定义字段:只对DB上的值运行to_python()? [英] Django Custom Field: Only run to_python() on values from DB?

查看:83
本文介绍了Django自定义字段:只对DB上的值运行to_python()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆