Виртуальное поле Django: установка значения свойства из виртуального поля

#python #django #django-models

#python #django #django-модели

Вопрос:

Я пытаюсь понять внутренности django ModelFields для реализации новой функции в django-hstore.

По сути, я хочу создавать виртуальные поля из словаря HStore, который имеет предопределенную схему.

В качестве первого шага я хотел бы скрыть фактическое поле словаря HStore и использовать вместо него значение, присутствующее в виртуальных полях, для составления окончательного словаря HStore.

Я смог заставить администратора работать должным образом для всех действий, за исключением действия сохранения, которое не сохраняет значение виртуального поля в словаре HStore.

Вот мой фактический код виртуального поля:

 # virtual.py
from django.db.models.fields import Field


class VirtualField(Field):
    """ Virtual Field """

    def __init__(self, *args, **kwargs):
        try:
            self.hstore_field_name = kwargs.pop('hstore_field_name')
        except KeyError:
            raise ValueError('missing hstore_field_name keyword argument')
        super(VirtualField, self).__init__(*args, **kwargs)

    def contribute_to_class(self, cls, name, virtual_only=True):
        super(VirtualField, self).contribute_to_class(cls, name, virtual_only)

    def value_from_object(self, obj):
        """
        Returns the value of this field in the given model instance.
        """
        hstore_field = getattr(obj, self.hstore_field_name)
        return hstore_field[self.attname]

    def save_form_data(self, instance, data):
        hstore_field = getattr(instance, self.hstore_field_name)
        hstore_field[self.attname] = data
        setattr(instance, self.hstore_field_name, hstore_field)
  

models.py (просто прототипирование)

 class ModeledDataBag(models.Model):
    name = models.CharField(max_length=32)
    data = hstore.ModeledDictionaryField(schema={
        'number': {
            'type': int,
            'default': 0
        }
    })

    number = VirtualField(hstore_field_name='data')

    objects = hstore.HStoreManager()
  

Я думал, что save_form_data поможет, но это не так.

В документах django я нашел раздел «Метакласс SubfieldBase» на странице «Поля пользовательской модели», который выглядит так, как мне нужно.

Это правильный путь для следования?

Есть ли какой-нибудь пример для изучения?

Кто-нибудь может привести пример того, как установить значение ключа «номер» поля hstore «данные» и сохранить его в базе данных? Оттуда я думаю, что знаю, как действовать дальше.

Спасибо…

Ответ №1:

Правильным ответом было использование дескрипторов python, реализованное решение здесь:

https://github.com/djangonauts/django-hstore/blob/8229e850e1631d8fd038436d2aa1fccb26b9a699/django_hstore/virtual.py#L29

Эта функция изначально была разработана для проекта с открытым исходным кодом под названием nodeshot, вот пример реализации со схемой, взятой из settings.py:

https://github.com/ninuxorg/nodeshot/blob/028bb28009bf73b2a4fc087f811e1b66c958907e/nodeshot/core/nodes/models/node.py#L49