64

Django モデルにデータを保存する必要があります。これらのデータは、モデルのすべてのインスタンスと同じではありません。

最初はモデルをサブクラス化することを考えていましたが、アプリケーションの柔軟性を維持しようとしています。サブクラスを使用すると、新しい種類のオブジェクトが必要になるたびにクラス全体を作成する必要があり、それは良くありません。また、余分なフィールドのペアを格納するためだけに、多くのサブクラスを作成することになります。

辞書を使うのが最善の方法だと思いますが、Django モデルに辞書を格納する方法について、Django のドキュメントには何もありません (または見つかりません)。

手がかりはありますか?

4

14 に答える 14

44

探しているデータが本当に辞書のようなものである場合は、コンテナである 1 つのモデルとキーと値のペアである別のモデルを使用した 2 レベルのセットアップを使用できる可能性があります。コンテナーのインスタンスを作成し、各キーと値のインスタンスを作成して、一連のキーと値のインスタンスをコンテナー インスタンスに関連付けます。何かのようなもの:

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を使用して辞書の内部にアクセス/検索できるようになりますが、ピクル/シリアル化ソリューションではできません。

于 2008-12-31T08:19:28.807 に答える
18

この余分なデータを使用してクエリを実行する必要がない場合は、シリアル化された辞書として保存できます。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])
于 2008-12-31T03:39:18.747 に答える
16

別のクリーンで高速なソリューションがここにあります: https://github.com/bradjasper/django-jsonfield

便宜上、簡単な説明をコピーしました。

インストール

pip install jsonfield

使用法

from django.db import models
from jsonfield import JSONField

class MyModel(models.Model):
    json = JSONField()
于 2013-07-31T12:50:28.747 に答える
14

「django store object」に対するGoogleの4番目の結果でこの投稿にたどり着きました

少し遅れましたが、django-picklefieldは私にとって良い解決策のようです。

ドキュメントの例:

使用するには、モデルでフィールドを定義するだけです:

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

好きなものを(ピクル可能である限り)フィールドに割り当てます。

>>> obj = SomeObject()
>>> obj.args = ['fancy', {'objects': 'inside'}]
>>> obj.save()
于 2011-09-19T10:10:04.323 に答える
8

ネッドが答えたように、辞書のアプローチを使用すると、「一部のデータ」を照会することはできません。

それでも辞書を保存する必要がある場合は、Marty Alchin の新しい本Pro Djangoに記載されている PickleField クラスが断然最良の方法です。このメソッドは、Python クラス プロパティを使用して、モデル フィールドに格納されている Python オブジェクトを必要に応じてピクル/ピクル解除します。

このアプローチの基本は、django のcontibute_to_classメソッドを使用してモデルに新しいフィールドを動的に追加し、getattr/setattr を使用してオンデマンドでシリアル化することです。

私が見つけることができる数少ないオンラインの例の 1 つは、このJSONFieldの定義です。

于 2008-12-31T07:44:46.600 に答える
6

あなたが解決しようとしている問題の性質について正確にはわかりませんが、不思議なことにGoogle App Engine の 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 フレームワークの両方をサポートしています。これがモデルを表現する最良の方法であるかどうかを調べる価値があるかもしれません。

従来のリレーショナル データベース モデルには、この種の列追加の柔軟性がありません。データ型が十分に単純である場合、@Ned Batchelderが提案するように、従来の RDBMS 哲学から抜け出し、シリアライゼーションを介して単一の列に値をハックすることができます。ただし、 RDBMS を使用する必要ある場合は、おそらく Django モデルの継承が適しています。特に、派生の各レベルに対して1 対 1 の外部キー関係が作成されます。

于 2008-12-31T07:09:29.697 に答える
3

Django-Geo には、役に立つと思われる "DictionaryField" が含まれています。

http://code.google.com/p/django-geo/source/browse/trunk/fields.py?r=13#49

一般に、データ全体に対してクエリを実行する必要がない場合は、非正規化アプローチを使用して余分なクエリを回避します。ユーザー設定は非常に良い例です。

于 2009-05-13T16:50:37.157 に答える
3

「モデルのすべてのインスタンスと等しくない」ということは、「スキーマのないデータベース」にぴったりのように思えます。CouchDBはそのアプローチの代表的なものであり、あなたはそれを検討するかもしれません。

あるプロジェクトで、Django ORM ではうまく機能しなかったいくつかのテーブルを CouchDB に移動しましたが、これには非常に満足しています。Django 固有の CouchDB モジュールを一切使用せずに、couchdb-pythonを使用しています。データ モデルの説明については、こちらを参照してください。Django の 5 つの「モデル」から Django の 3 つの「モデル」と 1 つの CouchDB「データベース」への移動により、実際には、アプリケーションのコードの合計行数がわずかに減少しました。

于 2009-01-04T12:28:20.570 に答える
3

他の方法で構造化されたデータを単一の列に詰め込むことを控える必要があることに同意します。しかし、そうしなければならない場合、Django にはXMLFieldが組み込まれています。

Django スニプレットにJSONFieldもあります。

于 2009-05-13T18:05:44.727 に答える
2

よく考えて、各データセットの共通点を見つけてください...次にモデルを定義します。サブクラスの使用が必要な場合とそうでない場合があります。共通点を表す外部キーは避けるべきではありませんが、意味がある場合は推奨されます。

ランダムデータをSQLテーブルに詰め込むことは、それが本当に非リレーショナルデータでない限り、賢明ではありません。その場合は、問題を定義してください。サポートできる場合があります。

于 2008-12-31T05:54:12.143 に答える
1

Postgres を使用している場合は、hstore フィールドを使用できます: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#hstorefield

于 2016-08-30T19:36:59.490 に答える