Pickled object field for Django
django-picklefield provides an implementation of a pickled object field for Django models. It enables storing any picklable Python object directly in a database field, handling automatic serialization and deserialization. The library is currently at version 3.4.0 and maintains a healthy release cadence, with updates typically occurring at least once a year to support newer Django and Python versions.
Warnings
- breaking Storing untrusted or user-controlled data directly in `PickledObjectField` can lead to arbitrary code execution (insecure deserialization). The Python `pickle` module is inherently unsafe when handling data from untrusted sources. `django-picklefield` explicitly marks the field as `editable=False` to prevent declarative usage in Django forms and the admin, but direct assignment of unsanitized user input remains a critical risk.
- gotcha Querying a `PickledObjectField` using `QuerySet.values()` or `QuerySet.values_list()` will return the raw, base64-encoded pickled string, not the deserialized Python object. You will need to manually decode and unpickle these values if you want the original Python objects.
- gotcha Directly storing instances of other Django models in a `PickledObjectField` can lead to issues due to how Django models manage their state and references, especially after model definition changes or during migrations.
- breaking Major versions of `django-picklefield` have specific compatibility requirements for Python and Django versions. For instance, version 3.4.0 supports Django 6.0 and Python 3.10+ (including Python 3.14), but dropped support for Python 3.9. Version 3.3.0 dropped support for Django 3.2, 4.0, and 4.1.
- gotcha If the class definition of an object stored in a `PickledObjectField` changes significantly after it has been pickled (e.g., attributes are removed, renamed, or types change), attempting to unpickle older data might result in `AttributeError`, `TypeError`, or other deserialization errors.
Install
-
pip install django-picklefield
Imports
- PickledObjectField
from picklefield.fields import PickledObjectField
Quickstart
import os
from django.db import models
from picklefield.fields import PickledObjectField
# Configure Django for a minimal setup (usually done in settings.py)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
# This is a dummy settings file for demonstration. In a real project,
# ensure 'picklefield' is in INSTALLED_APPS.
# A real settings.py would look something like:
# INSTALLED_APPS = ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'picklefield', 'myapp']
# DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}
# SECRET_KEY = 'insecure-dev-key'
class MyModel(models.Model):
data = PickledObjectField(compress=True)
def __str__(self):
return f"MyModel with data: {self.data}"
# Example Usage (assuming Django setup is complete, e.g., via manage.py shell)
if __name__ == '__main__':
# This part would typically be run within a Django shell or application context
# For a standalone runnable example, mocking Django ORM is complex.
# The following illustrates usage, but won't run directly without a full Django setup.
# Create a dummy class to demonstrate pickling custom objects
class CustomObject:
def __init__(self, name, value):
self.name = name
self.value = value
def __repr__(self):
return f"CustomObject(name='{self.name}', value={self.value})"
print("To run this, ensure Django is configured and 'picklefield' is in INSTALLED_APPS.")
print("Then run `python manage.py shell` and execute the following:")
print(" from myapp.models import MyModel")
print(" from myapp.quickstart import CustomObject") # assuming this code is in myapp/quickstart.py
print(" obj = MyModel()
obj.data = {'list': [1, 2, {'a': 3}], 'custom': CustomObject('test', 123)}
obj.save()
retrieved_obj = MyModel.objects.first()
print(f'Stored data: {retrieved_obj.data}')
print(f'Type of retrieved data: {type(retrieved_obj.data)}')
print(f'Type of custom object: {type(retrieved_obj.data["custom"])}')")