¿Cómo puedo asegurarme de que el método * to_python() * de mi campo personalizado solo se invoca cuando los datos en el campo se han cargado desde el DB?Campo personalizado de Django: ¿solo ejecuta to_python() en los valores de DB?
Estoy tratando de usar un campo personalizado para manejar la Codificación/Descodificación Base64 de una sola propiedad de modelo. Todo parecía funcionar correctamente hasta que instalé una nueva instancia del modelo y establecí esta propiedad con su valor de texto sin formato ... en ese punto, Django intentó decodificar el campo pero falló porque era texto sin formato.
El atractivo de la implementación del campo personalizado fue que pensé que podía manejar el 100% de la lógica de codificación/decodificación allí, de modo que ninguna otra parte de mi código alguna vez necesitó saberlo. ¿Qué estoy haciendo mal?
(NOTA: Esto es sólo un ejemplo para ilustrar mi problema, yo no necesito consejos sobre cómo debería o no debería estar utilizando la codificación Base64)
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)
... y se rompe cuando hago esto en el shell interactivo. ¿Por qué está llamando a topypy() aquí?
>>> 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
que había esperado que sería capaz de hacer algo como esto ...
>>> 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()
... ¿qué estoy haciendo mal?
Sí, eso se me ocurrió también ... Esperaba una solución más limpia. Soy bastante nuevo para Django en general, y específicamente esta es la primera vez que uso un campo personalizado, así que mi suposición es que o me falta algo en la declaración de mi campo personalizado, o que hay un completamente diferente, más apropiado forma de satisfacer mis necesidades –
Resulta que esta fue en realidad la única solución que pude encontrar. Decepcionado, no hay una mejor manera de hacer esto. –
Esto fallará si la información que almacena es válida como entrada Base64 (por ejemplo, 'b'abcd''). Entonces no se genera 'TypeError', y el resultado es incorrecto. –