透明地将Django模型字段存储为JSON数据

时间:2014-05-01 13:50:16

标签: python django model

说我有一个对象,"订单,"一个领域,"项目,"保存订单商品列表。永远不会在数据库中搜索或单独选择项目列表,因此我只想将其作为JSON字符串存储在DB字段中。

我试图找出嵌入此功能的最佳方式,因此对使用该模型的任何人来说都相当透明。我认为保存模型非常简单 - 只需覆盖保存方法并序列化"项目"列入内部" _items"字段,然后将其写入数据库。不过,我对如何反序列化感到困惑。在研究了可能用于创作的某种类方法,或者创建了一个定制的管理器,或者某些与信号有关的事情之后,我已经彻底迷惑了自己。我确信这已经解决了一百次,我很好奇人们认为最佳做法。

示例类:

class OrderItem():
    def __init__(self, desc="", qty=0):
        self.desc = desc
        self.qty = qty


class Order(Model):
    user = ForeignKey(User)
    _items = TextField() 

    def save(self, *args, **kwargs):
        self._items = jsonpickle.encode(self.items)
        super(Order, self).save(*args, **kwargs)

使用示例:

order = Order()
order.items = [OrderItem("widget", 5)]
order.save()

这将在数据库中创建一个记录

_items = [{"desc":"widget", "qty":5}]

现在我希望以后能够选择对象

order = Order.objects.get(id=whatever)

并让order.items成为解包的项目数组,而不是存储的JSON字符串。

修改

解决方案结果非常简单,我在这里张贴以防万一它可以帮助其他任何新手。根据丹尼尔的建议,我选择了这个自定义模型字段:

class JSONField(with_metaclass(SubfieldBase, TextField)):
    def db_type(self, connection):
        return 'JSONField'

    def to_python(self, value):
        if isinstance(value, basestring):
            return jsonpickle.decode(value)
        else:
            return value

    def get_prep_value(self, value):
        return jsonpickle.encode(value)

1 个答案:

答案 0 :(得分:1)

更好的方法是继承TextField并覆盖相关方法,以根据需要透明地执行序列化/反序列化。事实上,已经有很多这样的实现:例如here's one