Registry /
auth-security / django-encrypted-model-fields
Install & Compatibility
Where this runs
tested against v0.6.5 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.000s · 82.6MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 4.2s · import 0.000s · 83MB
82MB installed
● package 82MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
EncryptedCharField
✓ from encrypted_model_fields import EncryptedCharField
✗ from encrypted_model_fields.fields import EncryptedCharField
This quickstart demonstrates defining a Django model with `EncryptedCharField` and `EncryptedTextField`. It highlights the critical `ENCRYPTED_FIELD_KEYS` setting in `settings.py`, which maps key names to their actual encryption keys. Data saved using these fields will be automatically encrypted and decrypted on access. Note the use of `os.environ.get` for secure key management. The standalone script includes a simplified Django setup for immediate execution (requires `Django` to be installed), but in a real project, you'd integrate the models into your existing Django application and manage migrations via `manage.py`.
import os
from django.conf import settings
from django.db import models
# Minimal Django settings for standalone script testing
if not settings.configured:
settings.configure(
DEBUG=True,
INSTALLED_APPS=[
'encrypted_model_fields' # Required for migrations/field registration
],
DATABASES={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
},
# CRUCIAL: Define encryption keys
ENCRYPTED_FIELD_KEYS={
'default': os.environ.get('ENCRYPTED_FIELD_DEFAULT_KEY', 'a_secret_key_for_dev_or_testing_ONLY_do_not_use_in_prod'),
'billing': os.environ.get('ENCRYPTED_FIELD_BILLING_KEY', 'another_key_for_billing_data')
},
# Required for any Django project
SECRET_KEY='django-insecure-testkey-very-insecure'
)
# Ensure apps are loaded (needed for standalone scripts)
import django
django.setup()
from encrypted_model_fields.fields import EncryptedCharField, EncryptedTextField
class Customer(models.Model):
name = models.CharField(max_length=100)
email = EncryptedCharField(max_length=255)
notes = EncryptedTextField(blank=True, null=True, key_name='billing') # Use a specific key
def __str__(self):
return self.name
# Example usage (requires database setup, e.g., via manage.py migrate)
if __name__ == '__main__':
# This part would typically be in a Django shell or view
print("--- Quickstart Example ---")
# In a real Django project, you'd run 'python manage.py makemigrations' and 'python manage.py migrate'
# For this standalone script, we'll simulate migrations for Customer model
from django.apps import apps
from django.core.management.commands import makemigrations, migrate
from io import StringIO
# Simulate makemigrations
# Note: This is a hack for a standalone script, not for production use.
# In a real project, 'encrypted_model_fields' would be in INSTALLED_APPS and 'python manage.py makemigrations/migrate' would be run.
# Create a simple fake app for the model
class FakeAppConfig(apps.AppConfig):
name = 'my_app'
verbose_name = 'My App'
apps.apps_ready = False # Reset app loading for standalone execution
apps.clear_cache()
apps.set_available_apps(['my_app'])
apps.populate(settings.INSTALLED_APPS + ['my_app'])
settings.INSTALLED_APPS += ['my_app']
apps.get_app_config('my_app').models = {'customer': Customer}
# For real migration, save models.py in an app and run commands.
# For this quickstart, we'll just interact with the model directly in memory after setup.
# Create a record
customer = Customer.objects.create(name='Alice', email='alice@example.com', notes='Confidential billing info.')
print(f"Created customer: {customer.name}")
print(f"Stored email (encrypted): {customer.email}") # Will show encrypted value if accessed directly before decrypt
# Retrieve and decrypt
retrieved_customer = Customer.objects.get(name='Alice')
print(f"Retrieved email (decrypted): {retrieved_customer.email}")
print(f"Retrieved notes (decrypted): {retrieved_customer.notes}")
# Update
retrieved_customer.email = 'alice.smith@example.com'
retrieved_customer.save()
print(f"Updated email: {Customer.objects.get(name='Alice').email}")
Debug
Known issues
breakingData encrypted with versions prior to 0.6.0 (which used `pycrypto`) is NOT readable by versions 0.6.0 and later (which use `cryptography`). An explicit data migration is required if upgrading from versions < 0.6.0 to >= 0.6.0.fixBefore upgrading, decrypt all data using the old version, upgrade the library, then re-encrypt all data using the new version. This is a manual process and requires careful planning and backup.
affects: <0.6.0 to >=0.6.0
breakingThe `KEY_GENERATOR` and `KEY_STORE` settings were removed in version 0.6.0. They have been replaced by the `ENCRYPTED_FIELD_KEYS` dictionary setting.fixMigrate your `settings.py` to use `ENCRYPTED_FIELD_KEYS` as a dictionary mapping key names to their string values. For example, `ENCRYPTED_FIELD_KEYS = {'default': 'your_default_key', 'some_other_key': 'another_key'}`. affects: <0.6.0 to >=0.6.0
gotchaFailing to define `ENCRYPTED_FIELD_KEYS` in your Django `settings.py` or providing an invalid structure (e.g., not a dictionary or string) will lead to an `ImproperlyConfigured` exception or `MissingKeyError` when attempting to save or retrieve data.fixEnsure `ENCRYPTED_FIELD_KEYS` is defined in `settings.py` as a dictionary, with at least a 'default' key if not using explicit `key_name` arguments on fields. For production, keys should be loaded from environment variables or a secure secret management system, NOT hardcoded.
affects: >=0.6.0
Upgrade
Version history
0.6.5latest on PyPI · released Feb 24, 2022
Audit
Dependencies
DjangorequiredCore framework dependency, requires >=2.0
cryptographyrequiredProvides the underlying encryption primitives