python / expert
Snippet
Django Custom Model Field with from_db_value Transformation
Custom model fields in Django allow you to define how data is stored and retrieved from the database. The from_db_value method is called when loading data from the database, enabling on-the-fly transformations. This pattern is essential for implementing encryption at the field level, supporting legacy data formats, or creating computed fields that derive their values from other stored data.
snippet.py
1
import re\nfrom django.db import models\n\nclass EncryptedCharField(models.CharField):\n def __init__(self, *args, **kwargs):\n self.encryption_key = kwargs.pop('encryption_key', None)\n super().__init__(*args, **kwargs)\n\n def deconstruct(self):\n name, path, args, kwargs = super().deconstruct()\n if self.encryption_key:\n kwargs['encryption_key'] = self.encryption_key\n return name, path, args, kwargs\n\n def get_prep_value(self, value):\n if value is None:\n return value\n return self._encrypt(value)\n\n def from_db_value(self, value, expression, connection):\n if value is None:\n return value\n return self._decrypt(value)\n\n def _encrypt(self, value):\n if self.encryption_key:\n return f'ENC:{value[::-1]}'\n return value\n\n def _decrypt(self, value):\n if value and value.startswith('ENC:'):\n return value[4:][::-1]\n return value
django
Breakdown
1
class EncryptedCharField(models.CharField):
Defines a custom field inheriting from CharField, enabling reusable encrypted string storage across multiple models
2
def from_db_value(self, value, expression, connection):
Database value hook called during model hydration from DB, allowing transformation of raw stored values before assignment
3
def get_prep_value(self, value):
Prepares values before database insertion, applying encryption so plaintext never touches the database
4
def deconstruct(self):
Required for Django migrations to properly serialize custom field parameters like encryption_key during schema generation