Важнее некуда: В PickleField добавлена возможность полноценного хранения объектов моделей и поддержка питоновских значений по умолчанию.
Важно: предыдущая версия PickleField'а была практически неработающей в большинстве случаев. Теперь же появилось время в связи с ангиной, и я быстро исправил эту оплошность.
Иногда возникает необходимость хранить какие-то данные, "сериализированные" с помощью pickle или cPickle, в базе данных. Для этих случаев весьма кстати будет PickleField. Вообщем, может быть кому-то пригодится.
from django.conf import settings
from django.db import models
if getattr(settings, 'USE_CPICKLE', False):
import cPickle as pickle
else:
import pickle
class PickleField(models.TextField):
__metaclass__ = models.SubfieldBase
editable = False
serialize = False
def get_db_prep_value(self, value):
return pickle.dumps(value)
def to_python(self, value):
if not isinstance(value, basestring):
return value
# Tries to convert unicode objects to string, cause loads pickle from
# unicode excepts ugly ``KeyError: '\x00'``.
#
# If not possible, return this value, cause it's not pickled yet.
if isinstance(value, unicode):
try:
str_value = str(value)
except UnicodeEncodeError:
return value
else:
str_value = value
try:
return pickle.loads(str_value)
except ValueError:
# If pickle could not loads from string it's means that it's Python
# string saved to PickleField.
return value
Также добавил простейший тест для показания работы PickleField'a:
import unittest
from django.db import models
from fields import PickleField
class PickleObject(models.Model):
name = models.CharField(max_length=16)
data = PickleField()
class TestPickleField(unittest.TestCase):
def setUp(self):
PickleObject.objects.all().delete()
def test_not_string_data(self):
items = [
'Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'
]
obj = PickleObject.objects.create(name='default', data=items)
self.assertEqual(PickleObject.objects.count(), 1)
self.assertEqual(obj.data, items)
obj = PickleObject.objects.get(name='default')
self.assertEqual(obj.data, items)
def test_string_and_unicode_data(self):
DATA = (
('string', 'Simple string'),
('unicode', u'Simple unicode string'),
)
for name, data in DATA:
obj = PickleObject.objects.create(name=name, data=data)
self.assertEqual(obj.data, data)
self.assertEqual(PickleObject.objects.count(), 2)
for name, data in DATA:
obj = PickleObject.objects.get(name=name)
self.assertEqual(obj.data, data)
Надеюсь, что в скором времени эти изменения будут добавлены в django-fields.
4 комментариев:
Прикольно. Это твое? Не хочешь добавить в http://github.com/svetlyak40wt/django-fields/
Спасибо, мне пригодился. А где вы храните описания полей? Просто, на мой взгляд, смешивать их с моделями как-то быдловато.
fields.py? :)
https://github.com/shrubberysoft/django-picklefield - "по-настоящему рабочий PickledObjectField, инфа 100%", у вашего примера некоторые проблемы с не-ASCII символами.
http://bugs.python.org/issue2980 - а вот связанный недобаг.
Отправить комментарий