0

私の Google App Engine アプリには、保存する必要があるモデル オブジェクトがあります。これらのオブジェクトは、さまざまなポリシー オブジェクトによってパラメータ化されます。たとえば、私の Event クラスには、誰が表示、更新などを行えるかを決定する Privacy Policy オブジェクトがあります。PrivacyPolicy には、異なる動作をするさまざまなサブクラスがあります。イベントは、さまざまな時点でその PrivacyPolicy オブジェクトを調べます。

class PrivacyPolicy(db.Model):
    def can_see(self, event, user):
        pass

class OwnerOnlyPolicy(PrivacyPolicy):
    def can_see(self, event, user):
        return user == event.owner

class GroupOnlyPolicy(PrivacyPolicy):
    def can_see(self, event, user):
        for grp in event.owner.groups()
            if grp.is_member(user):
                return True
        return False

class OnlyCertainUsersPolicy(PrivacyPolicy):
    def __init__(self, others):
        self.others = others

    def can_see(self, event, user):
        return user in others

Event クラスに、PrivacyPolicy への ReferenceProperty を使用させることができます。

class Event(db.Model):
    privacy: db.ReferenceProperty(PrivacyPolicy)
    #…

私がこれを好まない理由は、1 対 1 の関係とは、ポリシー オブジェクトに対してクエリを実行する人が誰もいないことを意味し、ポリシーからその Event オブジェクトへの後方参照を維持する必要がなく、それ以外の方法がないことです。 PrivacyPolicy は、独立した db レベルのオブジェクトです。これは、Event オブジェクトの状態の一部であり、数値ではなく単なるオブジェクトであるという点で、IntegerProperty と機能的に同等です。具体的には、Event タイプに不明な、状態がゼロまたは多数の状態を持つことができるオブジェクトです。

そのような状況にどのようにアプローチするかについて話している人を見つけることができません。私が知らないツール/アプローチはありますか? 私はそれを吸い上げて参照プロパティを使用し、オーバーヘッドで地獄を使用しますか?

これを処理する他の唯一の方法がカスタム プロパティ タイプである場合は、それにアプローチする方法についてのアドバイスを歓迎します。私が最初に考えたのは、TextProperty を使用してポリシー オブジェクト ( policy) の文字列表現を格納し、必要に応じてデコードし、結果をキャッシュし、ポリシー オブジェクトに何らかの変更を加えてキャッシュを無効にし、文字列表現を更新することです。

4

2 に答える 2

1

これをデータストアに保存しようとすると、複雑になりすぎます。これは、データストアではなくコードに属します。

最も複雑でない方法は次のとおりです。

class Event(db.Model):
    privacy = db.IntegerProperty()

    def can_see(self, user):
        if self.privacy == PRIVACY_OWNER_ONLY:
            return user == event.owner
        else if self.privacy == PRIVACY_GROUP:
            for grp in self.owner.groups()
                if grp.is_member(user):
                    return True
            return False
于 2012-05-28T22:56:49.737 に答える
0

時には、正しいアプローチを考えるだけでよい場合もあります。解決策は、https://groups.google.com/forum/?fromgroups#! topic / google-appengine / bwMD0ZfRnJgで説明されているような、pickleを使用して値を保存および取得する新しい種類のプロパティを導入することです。

ピクルスが常に答えであるとは限らず、とにかくドキュメントが優れているので、もう少し洗練されたものが欲しかったので、ここに私のObjectReferenceタイプがあります。

import pickle
from google.appengine.ext import db

class ObjectProperty(db.Property):
    def __init__(self, object_type=None, verbose_name=None, to_store=pickle.dumps, from_store=pickle.loads, **kwds):
        """Initializes this Property with all the given options

        All args are passed to the superclass. The ones used specifically by this class are described here. For
        all other args, see base class method documentation for details.

        Args:
          object_type: If not None, all values assigned to the property must be either instances of this type or None
          to_store: A function to use to convert a property value to a storable str representation. The default is
            to use pickle.dumps()
          from_store: A function to use to convert a storable str representation to a property value. The default is
            to use pickle.loads()
        """
        if object_type and not isinstance(object_type, type):
            raise TypeError('object_type should be a type object')

        kwds['indexed'] = False         # It never makes sense to index pickled data
        super(ObjectProperty, self).__init__(verbose_name, **kwds)

        self.to_store = to_store
        self.from_store = from_store
        self.object_type = object_type

    def get_value_for_datastore(self, model_instance):
        """Get value from property to send to datastore.

        We retrieve the value of the attribute and return the result of invoking the to_store function on it

        See base class method documentation for details.
        """
        value = getattr(model_instance, self.name, None)
        return self.to_store(value)

    def make_value_from_datastore(self, rep):
        """Get value from datastore to assign to the property.

        We take the value passed, convert it to str() and return the result of invoking the from_store function
        on it. The Property class assigns this returned value to the property.

        See base class method documentation for details.
        """
        # It passes us a unicode, even though I returned a str, so this is required
        rep = str(rep)
        return self.from_store(rep)

    def validate(self, value):
        """Validate reference.

        Returns:
          A valid value.

        Raises:
          BadValueError for the following reasons:
            - Object not of correct type.
        """
        value = super(ObjectProperty, self).validate(value)

        if value is not None and not isinstance(value, self.object_type):
            raise db.KindError('Property %s must be of type %s' % (self.name, self.object_type))

        return value
于 2012-06-01T15:13:17.480 に答える