Посты с тэгом custom model fields


Заставляем кастомные поля для моделей работать под Django 1.2+

Некоторое время тому назад я разработал несколько кастомных полей для моделей, таких как PickleField и JSONField и все было в них хорошо. Но время ведь не стоит на месте и мне захотелось окончательно перейти в своих проектах на прекрасную Django 1.2+ и использовать ее бенефиты вместе с использованием моих старых кастомных полей.

Для начала я просто попробовал запустить свой проект под Django 1.2 и сразу же получил вылетающие тесты при попытках считать любые данные из базы данных для моделей, содержащих кастомное поле. Ошибкой был обыкновенный ObjectDoesNotExist, который сразу натолкнул меня на мысль что проблема где-то в get_db_prep_value методе.

Открыв документ



И опять про PickleField

Давным-давно я написал более менее работающий пример PickleField'а - поля для хранения любого питоновского объекта, поддерживающего сериализацию при помощи pickle или cPickle.

И все бы неплохо, только на днях мне понадобилось хранить в этих PickleField'ах Django'вские модели, например экземпляры пользователей (auth.User) или проектов (самописная модель). Да, возможно, это не совсем верно, но задача стояла именно такая.

Не надеясь получить какой-то подвох я стал просто сохранять эти instance, и вроде бы все работало, пока я не написал смехотворный тест:

project = choice(Project.objects.all())
user = choice(project.users.all())

PickleModel.objects.create(object_field=project)
obj = PickleModel.objects.get(object_field=project)
obj.object_field = user
obj.save()

obj = PickleModel.objects.get(object_field=user)
obj.


Простой и работающий JSONField для Django

Не успел, я починить PickleField для Django, мне понадобилось создать JSONField. Задача оказалась решенной на раз/два, плюс ко всему добавился маленький и полезный виджет для JSONField'а, который показывает красиво отформатированный JSON в textarea. Сразу скажу, что contribute_to_class метод чуть менне, чем полностью, скопипастен с снипетта 377.

from django.conf import settings
from django.forms.widgets import Textarea
from django.db.models import SubfieldBase, TextField
from django.utils import simplejson


class JSONField(TextField):
    __metaclass__ = SubfieldBase

    def contribute_to_class(self, cls, name):
        super(JSONField, self).contribute_to_class(cls, name)

        def get_json(model):
            return self.get_db_prep_value(getattr(model, self.attname))
 


По-настоящему, рабочий Django PickleField

Важнее некуда: В 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):