2008-12-31 34 views
44

我需要在Django模型中存储一些数据。这些数据不等于模型的所有实例。如何在Django模型上存储字典?

起初我想到了模型的子类,但我试图保持应用程序的灵活性。如果我使用子类,每次需要新类型的对象时,我都需要创建一个完整的类,这并不好。我最终还会得到很多子类来存储一对额外的字段。

我真的觉得字典是最好的方法,但Django文档中没有关于在Django模型中存储字典的任何内容(或者我找不到它)。

任何线索?

+6

“一些数据” - 定义不明确。没有一些数据模型或其他提示,就没有答案。 – 2008-12-31 03:29:32

回答

32

如果它真的是你想要的任意数据字典,你可以使用一个两层设置,一个模型是一个容器,另一个模型是键值对。您将创建容器实例,创建每个键值实例,并将键值实例集与容器实例相关联。喜欢的东西:

class Dicty(models.Model): 
    name  = models.CharField(max_length=50) 

class KeyVal(models.Model): 
    container = models.ForeignKey(Dicty, db_index=True) 
    key  = models.CharField(max_length=240, db_index=True) 
    value  = models.CharField(max_length=240, db_index=True) 

它不漂亮,但它会告诉你访问/搜索使用DB字典的内部结构,而泡菜/序列化的解决方案不会。

+4

唯一的缺点是会追加一个数据库查询 – 2010-05-07 21:28:56

14

如果您不需要通过任何这些额外的数据进行查询,那么您可以将它作为序列化字典存储。使用repr将字典转换为字符串,并使用eval将字符串转换回字典。注意eval字典中没有用户数据,或使用safe_eval实现。

2

想一想,找出每个数据集的共同点......然后定义你的模型。它可能需要使用子类或不需要。代表共同性的外键是不可避免的,但是当它们有意义时会被鼓励。

将随机数据填充到SQL表中并不聪明,除非它是真正的非关系数据。如果是这种情况,请定义您的问题,我们可能会提供帮助。

+1

+1:不要随意将Python对象填充到表中。 – 2008-12-31 11:27:09

4

我不确定你想要解决的问题的性质,但它听起来很奇怪,类似于Google App Engine's BigTable Expando

Expandos允许您在运行时在数据库支持的对象实例上指定和存储附加字段。引用来自文档:

import datetime 
from google.appengine.ext import db 

class Song(db.Expando): 
    title = db.StringProperty() 

crazy = Song(title='Crazy like a diamond', 
      author='Lucy Sky', 
      publish_date='yesterday', 
      rating=5.0) 

crazy.last_minute_note=db.Text('Get a train to the station.') 

Google App Engine目前支持Python和Django框架。如果这是表达模型的最佳方式,可能值得研究。

传统的关系数据库模型没有这种列添加灵活性。如果您的数据类型足够简单,您可以通过序列化将传统的RDBMS理念和破解值打破为一列,如@Ned Batchelder提出的那样;然而,如果你的使用RDBMS,Django模型继承可能是一条路。值得注意的是,它将为每个推导级别创建a one-to-one foreign key关系。

7

正如Ned所回答的,如果您使用字典方式,您将无法查询“某些数据”。

如果你仍然需要存储字典,那么目前最好的方法是在Marty Alchin的新书Pro Django中记录的PickleField类。此方法使用Python类属性来腌/取消只存储在模型字段中的python对象。

这种方法的基础是使用django的contibute_to_class方法为您的模型动态添加一个新字段,并使用getattr/setattr进行按需序列化。

我能找到的几个在线例子之一就是JSONField的这个定义。

3

“不等于模型的所有实例”对我来说听起来像是一个“无模式数据库”的良好匹配。 CouchDB是该方法的招牌小孩,您可能会考虑这一点。

在一个项目中,我将Django ORM从来没有玩过的很多表移到CouchDB上,我对此很满意。我使用couchdb-python,没有任何Django特定的CouchDB模块。数据模型的描述可以在here找到。从Django中的五个“模型”到Django中的三个“模型”和一个CouchDB“数据库”的移动实际上略微减少了我的应用程序中的代码总数。

3

我同意你需要将其他结构化数据填充到单个列中。但是,如果你必须这样做,Django有一个内置的XMLField

Django snipplets还有JSONField

10

我来到这个岗位由谷歌的4rth结果“Django的存储对象”

有点晚,但django-picklefield看起来很好的解决方案给我。从文档

例子:

要使用,只是在你的模型中定义一个字段:

>>> from picklefield.fields import PickledObjectField 
>>> class SomeObject(models.Model): 
>>>  args = PickledObjectField() 

,并分配任何你喜欢的(只要它是picklable)到外地:

>>> obj = SomeObject() 
>>> obj.args = ['fancy', {'objects': 'inside'}] 
>>> obj.save() 
6

另一个干净而快速的解决方案可以在这里找到:https://github.com/bradjasper/django-jsonfield

为了方便起见,我复制了简单的说明。

安装

pip install jsonfield 

使用

from django.db import models 
from jsonfield import JSONField 

class MyModel(models.Model): 
    json = JSONField() 
相关问题