Say I have an object, "Order," a field of which, "items," holds a list of order items. The list of items will never be searched or individually selected in the database so I just want to store it in a DB field as a JSON string.
假设我有一个对象,“Order”,其中的一个字段“items”包含一个订单项列表。项目列表永远不会被搜索,也不会在数据库中单独选择,所以我只想将它作为JSON字符串存储在DB字段中。
I'm trying to figure out the best way to embed this functionality so it's fairly transparent to anyone using the model. I think saving the model is pretty easy - just override the save method and serialize the "items" list into an internal "_items" field, and then write that to the db. I'm confused about how to deserialize, though. Having looked into possibly some kind of classmethod for creation, or creating a custom manger, or something to do with signals, I've thoroughly confused myself. I'm sure this has been solved a hundred times over and I'm curious what people consider to be best practice.
我想找出最好的方法来嵌入这个功能,这样对于任何使用这个模型的人来说都是透明的。我认为保存模型非常简单——只需覆盖save方法并将“items”列表序列化为内部的“_items”字段,然后将其写入db。但是我对如何反序列化感到困惑。我已经研究了一些创建的类方法,或者创建了一个自定义的管理器,或者与信号有关的一些东西,我已经彻底把自己弄糊涂了。我确信这已经解决了一百次了,我很好奇人们认为什么是最佳实践。
Example classes:
示例类:
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)
Example usage:
使用示例:
order = Order()
order.items = [OrderItem("widget", 5)]
order.save()
This would create a record in the DB in which
这将在DB中创建一个记录
_items = [{"desc":"widget", "qty":5}]
Now I want to be able to later select the object
现在我想以后能够选择对象
order = Order.objects.get(id=whatever)
and have order.items be the unpacked array of items, not the stored JSON string.
和有秩序。项目是项目的未打包数组,而不是存储的JSON字符串。
EDIT:
编辑:
The solution turned out to be quite simple, and I'm posting here in case it helps any other newbies. Based on Daniel's suggestion, I went with this custom model field:
这个解决方案其实很简单,我在这里发布,以防对其他新手有帮助。根据Daniel的建议,我选择了这个自定义模型领域:
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 个解决方案
#1
1
A much better approach is to subclass TextField and override the relevant methods to do the serialization/deserialization transparently as required. In fact there are a number of implementations of this already: here's one, for example.
更好的方法是子类化TextField并重写相关的方法,以便根据需要透明地执行序列化/反序列化。事实上,已经有许多这样的实现了:例如,这里有一个。
#1
1
A much better approach is to subclass TextField and override the relevant methods to do the serialization/deserialization transparently as required. In fact there are a number of implementations of this already: here's one, for example.
更好的方法是子类化TextField并重写相关的方法,以便根据需要透明地执行序列化/反序列化。事实上,已经有许多这样的实现了:例如,这里有一个。