Saltar al contenido

¿Cómo puedo crear un campo django cifrado que convierta los datos cuando se recuperan de la base de datos?

Solución:

Creo que el problema es que to_python también se llama cuando asigna un valor a su campo personalizado (como parte de la validación puede ser, según este enlace). Entonces, el problema es distinguir entre las llamadas to_python en las siguientes situaciones:

  1. Cuando Django asigna un valor de la base de datos al campo (ahí es cuando desea descifrar el valor)
  2. Cuando asigna manualmente un valor al campo personalizado, por ejemplo, record.field = value

Un truco que podría usar es agregar un prefijo o sufijo a la cadena de valor y verificar eso en lugar de hacer isinstance cheque.

Iba a escribir un ejemplo, pero encontré este (incluso mejor :)).

Cheque BaseEncryptedField: https://github.com/django-extensions/django-extensions/blob/2.2.9/django_extensions/db/fields/encrypted.py (enlace a una versión anterior porque el campo se eliminó en 3.0.0; consulte el problema # 1359 por motivo de desaprobación)

Fuente: Campo personalizado de Django: ¿ejecutar solo to_python () en valores de la base de datos?

Deberías estar anulando to_python, como lo hizo el fragmento.

Si echa un vistazo a la CharField clase, puedes ver que no tiene una value_to_string método:

  • django/db/models/fields/__init__.py

Los docs dicen que el to_python El método debe lidiar con tres cosas:

  • Una instancia del tipo correcto
  • Una cadena (por ejemplo, de un deserializador).
  • Lo que sea que devuelva la base de datos para el tipo de columna que está utilizando.

Actualmente solo se ocupa del tercer caso.

Una forma de manejar esto es crear una clase especial para una cadena descifrada:

class DecryptedString(str):
   pass

Entonces puedes detectar esta clase y manejarla en to_python():

def to_python(self, value):
    if isinstance(value, DecryptedString):
        return value

    decrypted = self.encrypter.decrypt(encrypted)
    return DecryptedString(decrypted)

Esto le impide descifrar más de una vez.

Olvidó configurar la metaclase:

class EncryptedCharField(models.CharField):
    __metaclass__ = models.SubfieldBase

La documentación de campos personalizados explica por qué esto es necesario.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *