2008-12-31 74 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() 
相關問題