3

最近はMongoEngineをよく使っています。MongoDB の統合とは別に、エンティティの構造を明示的に定義するというアイデアが気に入っています。フィールド定義により、コードが理解しやすくなります。また、これらの定義を使用して、オブジェクトを検証して潜在的なバグを見つけたり、より正確にシリアライズ/デシリアライズしたりできます。

MongoEngine の問題は、ストレージ エンジンで動作するように特別に設計されていることです。同じことが Django と SQLAlchemy モデルにも当てはまり、リストとセットの型もありません。私の質問は、自動化されたオブジェクトの検証とシリアライゼーションを行う Python 用のオブジェクト スキーマ/モデル ライブラリはありますか?

例を挙げましょう。

class Wheel(Entity):
    radius = FloatField(1.0)


class Bicycle(Entity):
    front = EntityField(Wheel)
    back = EntityField(Wheel)


class Owner(Entity):
    name = StringField()
    bicycles = ListField(EntityField(Bicycle))


owner = Owner(name='Eser Aygün', bicycles=[])

bmx = Bicycle()
bmx.front = Wheel()
bmx.back = Wheel()

trek = Bicycle()
trek.front = Wheel(1.2)
trek.back = Wheel(1.2)

owner.bicycles.append(bmx)
owner.bicycles.append(trek)

owner.validate()  # checks the structure recursively

構造が与えられているため、オブジェクトのシリアライズとデシリアライズも簡単です。たとえばowner.jsonify()、辞書を返す場合があります

{
    'name': 'Eser Aygün',
    'bicycles': [{
        'front': {
            radius: 1.0
        },
        'back': {
            radius: 1.0
        }
    }, {
        'front': {
            radius: 1.2
        },
        'back': {
            radius: 1.2
        }
    }],
}

を呼び出して簡単に元に戻すことができますowner.dejsonify(dic)

4

4 に答える 4

1

あなたが説明していることは、オブジェクトの構造を検証してJSONとの間で簡単にマーシャリングできるようにするメカニズム(と呼ばれる)を含むremoteobjectsで実現できます。dataobject

また、HTTP 要求を行う REST クライアント ライブラリを構築するための機能もいくつか含まれていますが、この部分の使用は必須ではありません。

メインのディストリビューションには特定のor型remoteobjectsは付属していませんが、実装するのは簡単です。これは、私が管理しているコードベースの例で、 を使用しています:StringFieldIntegerFieldBooleanFieldremoteobjects

class BooleanField(dataobject.fields.Field):

    def encode(self, value):
        if value is not None and type(value) is not bool:
            raise TypeError("Requires boolean")
        return super(BooleanField, self).encode(value)

これは、オブジェクト定義で使用できます。

class ThingWithBoolean(dataobject.DataObject):
    my_boolean = BooleanField()

その後:

thing = ThingWithBoolean.from_dict({"my_boolean":true})
thing.my_boolean = "hello"
return json.dumps(thing.to_dict()) # will fail because my_boolean is not a boolean
于 2013-03-28T22:19:25.953 に答える
1

mongopersistZODB などの Python オブジェクトの永続化レイヤーとして mongo を使用する を確認してください。スキーマの検証は実行しませんが、Mongo と Python の間で透過的にオブジェクトを移動できます。

検証またはその他のシリアライゼーション/デシリアライゼーションのシナリオ (フォームなど) については、 を検討してcolanderください。水切りプロジェクトの説明:

Colander は、XML、JSON、HTML フォーム ポスト、またはその他の同様に単純なデータ シリアル化によって取得されたデータを検証および逆シリアル化するためのシステムとして役立ちます。Python 2.6、2.7、および 3.2 で動作します。コランダーは次の目的で使用できます。

  • データ スキーマを定義します。
  • データ スキーマに対してデータ構造を検証した後、文字列、マッピング、およびリストで構成されるデータ構造を任意の Python 構造に逆シリアル化します。
  • 任意の Python 構造を、文字列、マッピング、およびリストで構成されるデータ構造にシリアル化します。
于 2013-03-28T22:22:51.483 に答える
0

以前のコメントで述べたように、私は自分の車輪を発明することにしました。私はオープンソースの Python ライブラリEntitiesの実装を開始しました。https://github.com/eseraygun/python-entities/から確認できます。

このライブラリは、再帰的および非再帰的なコレクション タイプ (リスト、セット、辞書)、ネストされたエンティティ、および参照フィールドをサポートしています。複雑なエンティティのハッシュ可能なキーを自動的に検証、シリアライズ、デシリアライズ、および生成できます。(実際、デシリアライゼーション機能はまだ完全ではありません。)

これはあなたがそれを使用する方法です:

from entities import *

class Account(Entity):
    id = IntegerField(group=PRIMARY)  # this field is in primary key group
    iban = IntegerField(group=SECONDARY)  # this is in secondary key group
    balance = FloatField(default=0.0)

class Name(Entity):
    first_name = StringField(group=SECONDARY)
    last_name = StringField(group=SECONDARY)

class Customer(Entity):
    id = IntegerField(group=PRIMARY)
    name = EntityField(Name, group=SECONDARY)
    accounts = ListField(ReferenceField(Account), default=list)

# Create Account objects.
a_1 = Account(1, 111, 10.0)  # __init__() recognizes positional arguments
a_2 = Account(id=2, iban=222, balance=20.0)  # as well as keyword arguments

# Generate hashable key using primary key.
print a_1.keyify()  # prints '(1,)'

# Generate hashable key using secondary key.
print a_2.keyify(SECONDARY)  # prints '(222,)'

# Create Customer object.
c = Customer(1, Name('eser', 'aygun'))

# Generate hashable key using primary key.
print c.keyify()  # prints '(1,)'

# Generate hashable key using secondary key.
print c.keyify(SECONDARY)  # prints '(('eser', 'aygun'),)'

# Try validating an invalid object.
c.accounts.append(123)
try:
    c.validate()  # fails
except ValidationError:
    print 'accounts list is only for Account objects'

# Try validating a valid object.
c.accounts = [a_1, a_2]
c.validate()  # succeeds
于 2013-04-01T20:34:46.187 に答える