Django HStore:如何覆盖键值模型字段的 __getattr__ 和 __setattr__

Posted

技术标签:

【中文标题】Django HStore:如何覆盖键值模型字段的 __getattr__ 和 __setattr__【英文标题】:Django HStore: How to override a key-value model field's __getattr__ and __setattr__ 【发布时间】:2013-12-10 17:03:46 【问题描述】:

通过django-hstore module,在 Django 中使用 hstore 时,我的脚已经湿透了。使用hstore 的一大优势是它允许将键值存储在字段中,同时在 Postgresql 中提供良好的索引。 django-hstore(和一般的hstore)的一大缺点是您只能将值存储为字符串。

为了克服这个问题,我认为最好覆盖模型字段 (hstore.DictionaryField),这样输入到该字段的任何数据都会自动以 JSON 编码,检索到的任何数据都会自动从 JSON 解码。我试图通过覆盖__setattr__ 方法来做到这一点,但这会导致大量错误(当正在设置该字段的所有属性时)。有什么正确方法的想法吗?

到目前为止我所做的(我在关注 setter 的同时注释掉了 getter 部分,但留下了它以显示我的想法):

import simplejson as json

from django.db import models
from django_hstore import hstore


def _unpack_json(value):
    try:
        value = json.loads(value)
    except TypeError:
        pass
    return value


class HStoreJsonDict(hstore.DictionaryField):

    @staticmethod
    def _load_json(value):
        try:
            value = json.dumps(value)
        except Exception as e:
            # Is this needed?
            print(value, e)
            pass
        return value

    # def __getattribute__(self, key):
    #     print('__getattribute__')
    #     value = super(HStoreJsonDict, self).__getattribute__(key)
    #     return _unpack_json(value)

    # def __getitem__(self, key):
    #     print('__getitem__')
    #     value = super(HStoreJsonDict, self).__getitem__(key)
    #     return _unpack_json(value)

    def __setattr__(self, key, value):
        print('__setattr__', key, value)
        value = self._load_json(value)
        return super(HStoreJsonDict, self).__setattr__(key, value)

class TestModel(models.Model):
    name = models.CharField(max_length=64)
    data = HStoreJsonDict(db_index=True)
    objects = hstore.HStoreManager()

    def __unicode__(self):
        return '%s - %s' % (self.name, self.data)

【问题讨论】:

【参考方案1】:

归根结底,我发现最容易派生出django-hstore 模块并将序列化/反序列化放在DictionaryFieldget_prep_value()to_python() 方法中(see here for code)。

对于其他希望在使用 Django 时操作数据库的入口/检索数据的人,我强烈建议您查看 Django 的文档 to_python() 和 get_prep_value()。

【讨论】:

以上是关于Django HStore:如何覆盖键值模型字段的 __getattr__ 和 __setattr__的主要内容,如果未能解决你的问题,请参考以下文章

如何创建作为多个查询联合的 Django 模型字段,以实现覆盖字段?

hstore或json数据的Django数字比较?

如何在 django rest 框架 ModelSerializer 中覆盖模型字段验证

Postgresql:如何在不使用中间 hstore 的情况下将键值表转换为 json

Django ORM & hstore:计算键的唯一值

Django 模型:覆盖字段返回值