Djangoモデルにデータを保存する必要があります。これらのデータは、モデルのすべてのインスタンスと同じではありません。
最初はモデルをサブクラス化することを考えましたが、アプリケーションの柔軟性を維持しようとしています。サブクラスを使用する場合、新しい種類のオブジェクトが必要になるたびにクラス全体を作成する必要がありますが、それは良くありません。また、追加のフィールドのペアを格納するためだけに多くのサブクラスを作成します。
辞書が最善のアプローチだと思いますが、Djangoモデルに辞書を保存することに関するDjangoドキュメントには何もありません(または見つかりません)。
手がかりはありますか?
探している任意のデータのような辞書である場合は、コンテナであるモデルとキーと値のペアである別のモデルで2レベルのセットアップを使用できます。コンテナのインスタンスを作成し、各Key-Valueインスタンスを作成し、一連のKey-Valueインスタンスをコンテナインスタンスに関連付けます。何かのようなもの:
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を使用して辞書の内部にアクセス/検索できるのに対し、pickle/serializeソリューションはそうではありません。
この追加データのいずれかでクエリする必要がない場合は、serialized dictionaryとして保存できます。 repr
を使用して辞書をストリングに変換し、eval
を使用してストリングを辞書に戻します。辞書にユーザーデータがないことをevalで注意するか、safe_eval
実装。
たとえば、create
のupdate
およびviews
メソッドでは、次を追加できます。
if isinstance(request.data, dict) == False:
req_data = request.data.dict().copy()
else:
req_data = request.data.copy()
dict_key = 'request_parameter_that_has_a_dict_inside'
if dict_key in req_data.keys() and isinstance(req_data[dict_key], dict):
req_data[dict_key] = repr(req_data[dict_key])
「Djangoストアオブジェクト」に対するGoogleの4番目の結果によってこの投稿に行きました。
少し遅れましたが、 Django-picklefield は私にとっては良い解決策のようです。
ドキュメントの例:
使用するには、モデルにフィールドを定義するだけです:
>>> from picklefield.fields import PickledObjectField
>>> class SomeObject(models.Model):
>>> args = PickledObjectField()
そして、あなたが好きなものを(ピクル可能であれば)フィールドに割り当てます:
>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()
別のクリーンで高速なソリューションはここにあります: https://github.com/bradjasper/Django-jsonfield
便宜上、簡単な手順をコピーしました。
インストール
pip install jsonfield
使用法
from Django.db import models
from jsonfield import JSONField
class MyModel(models.Model):
json = JSONField()
Nedが答えたように、ディクショナリアプローチを使用する場合、「一部のデータ」をクエリすることはできません。
それでも辞書を保存する必要がある場合、Marty Alchinの新しい本Pro Djangoに文書化されているPickleFieldクラスが最善のアプローチです。このメソッドは、Pythonクラスプロパティを使用して、モデルフィールドに格納されているpythonオブジェクトをオンデマンドでピクル/アンピクルします。
このアプローチの基本は、Djangoの contibute_to_class
メソッドを使用して新しいフィールドをモデルに動的に追加し、getattr/setattrを使用してオンデマンドでシリアル化することです。
似たようなオンラインの例の1つは、この JSONField の定義です。
「モデルのすべてのインスタンスに等しくない」ということは、「スキーマフリーデータベース」にぴったりのように思えます。 CouchDB はそのアプローチのポスターの子であり、あなたはそれを考慮するかもしれません。
プロジェクトで、Django ORMで非常にナイスなプレイをしたことがないテーブルをいくつか、CouchDBに移動しました。とても満足しています。 couchdb-python なしでDjango固有のCouchDBモジュールのいずれか。データモデルの説明を見つけることができます こちら 。Django= to 3 "models"の5つの「モデル」からの動きin Djangoと1つのCouchDB "データベース"は、実際に私のアプリケーションのコードの合計行をわずかに減らしました。
この質問は古いですが、私は同じ問題を抱えていたので、ここで終了し、選択した答えは私の問題を解決できませんでした。
辞書をDjangoまたはREST Api、フロントエンドのオブジェクトとして使用するか、データが必ずしも同じ構造で、私が使用したソリューションが役立ちます。
APIにデータを保存するときは、 json.dump() メソッドを使用して、この question で説明されているように、適切なjson形式で保存できるようにします。
この構造を使用する場合、データはすでに適切なjson形式であり、ajax(または何でも)呼び出しで JSON.parse() でフロントエンドで呼び出されます。
Django-Geoには、役立つと思われる「DictionaryField」が含まれています。
http://code.google.com/p/Django-geo/source/browse/trunk/fields.py?r=13#49
一般に、データ全体をクエリする必要がない場合は、非正規化アプローチを使用して余分なクエリを回避します。ユーザー設定は非常に良い例です!
考え直して、各データセットの共通点を見つけてから、モデルを定義してください。サブクラスの使用が必要な場合とそうでない場合があります。共通性を表す外部キーは避けるべきではありませんが、意味がある場合は推奨されます。
ランダムデータをSQLテーブルに詰め込むのは、それが本当に非リレーショナルデータでない限り、賢明ではありません。その場合は、問題を定義してください。サポートできる場合があります。
Postgresを使用している場合、hstoreフィールドを使用できます: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield 。
テキストフィールドとjson.loads()
/json.dumps()
を使用します
models.py
import json
from Django.db import models
class Item(models.Model):
data = models.TextField(blank=True, null=True, default='{}')
def save(self, *args, **kwargs):
## load the current string and
## convert string to python dictionary
data_dict = json.loads(self.data)
## do something with the dictionary
for something in somethings:
data_dict[something] = some_function(something)
## if it is empty, save it back to a '{}' string,
## if it is not empty, convert the dictionary back to a json string
if not data_dict:
self.data = '{}'
else:
self.data = json.dumps(data_dict)
super(Item, self).save(*args, **kwargs)