django-fernet-fields-v2 provides Fernet symmetric encryption for Django model fields, leveraging the `cryptography` library. It is a fork of `django-fernet-fields`, specifically updated to support Django 4 and later versions, as well as Python 3.8+. The current version is 0.9, released in August 2023, with releases typically occurring on an as-needed basis to maintain compatibility.
pip install django-fernet-fields-v2Verified import paths — ran on the pinned version, not inferred.
To use `django-fernet-fields-v2`, define encrypted fields in your Django models by importing them from `fernet_fields`. Ensure your `settings.py` includes a `SECRET_KEY` (which it uses by default) or `FERNET_KEYS` for explicit key management. Then, create and apply migrations as usual. Data assigned to these fields will be automatically encrypted before saving to the database and decrypted upon retrieval.
Securely store your `SECRET_KEY` and any `FERNET_KEYS` in environment variables or a secrets management system. Implement robust backup strategies for your keys.
Avoid applying `db_index=True` or `unique=True` to Fernet fields. For searchability or uniqueness, consider storing a hashed, non-sensitive version of the data in a separate, non-encrypted field, or design your application to retrieve and filter data in memory after decryption.
For full key rotation, you must perform a data migration. This typically involves iterating through all instances of models with encrypted fields, re-saving them (`instance.save()`) after the new key is placed at the head of `FERNET_KEYS`. Ensure old keys remain in `FERNET_KEYS` (after the new key) until all data is re-encrypted to allow decryption of existing values during the transition.
Increase the `max_length` of `FernetCharField` fields beyond what would be needed for the plaintext. A common recommendation is to allow for at least 2x-3x the original length, plus a small overhead (e.g., if plaintext is 255 chars, use 765 or more).
If this information leakage is a concern, avoid nullable encrypted fields. Instead, store a specific 'empty' sentinel value (which will be encrypted like any other data) in a non-nullable encrypted field.