動的に作成された文字列 (「Pigeon」など) を取得して、Google App Engine に「Pigeon」という名前のこのプロジェクトで定義されたモデル クラスがあるかどうかを実行時に判断できるようにしたいと考えています。「Pigeon」が既存のモデル クラスの名前である場合、そのように定義された Pigeon クラスへの参照を取得したいと思います。
また、この場合の動的文字列「Pigeon」は外部から取得されるため、eval はまったく使用したくありません。
動的に作成された文字列 (「Pigeon」など) を取得して、Google App Engine に「Pigeon」という名前のこのプロジェクトで定義されたモデル クラスがあるかどうかを実行時に判断できるようにしたいと考えています。「Pigeon」が既存のモデル クラスの名前である場合、そのように定義された Pigeon クラスへの参照を取得したいと思います。
また、この場合の動的文字列「Pigeon」は外部から取得されるため、eval はまったく使用したくありません。
実際、ソースコードとインターウェブを調べてみると、法案に適合していると思われる文書化されていない方法が見つかりました。
from google.appengine.ext import db
key = "ModelObject" #This is a dynamically generated string
klass = db.class_for_kind(key)
このメソッドは、クラスが存在しない場合に説明的な例外をスローするため、キー文字列が外部からのものである場合は、おそらくそれをキャッチする必要があります。
おそらく非常に悪い習慣ですが、試すことができます:
def get_class_instance(nm) :
try :
return eval(nm+'()')
except :
return None
また、より安全にするために、eval にローカル ハッシュを与えることができます。eval(nm+'()', {'Pigeon':pigeon})
それが機能するかどうかはわかりませんが、間違いなく問題があります。 の値と呼ばれる関数がある場合、次のnm
ように返されます。
def Pigeon() :
return "Pigeon"
print(get_class_instance('Pigeon')) # >> 'Pigeon'
編集:モジュールを知っている場合、別の方法はおそらく(テストされていません)です:(
申し訳ありませんが、それはobj.hasattrではなく、hasattr(obj)です!)
import models as m
def get_class_instance(nm) :
if hasattr(m, nm) :
return getattr(m, nm)()
else : return None
EDIT 2:はい、うまくいきます!ウー!
内部の詳細に依存せずにこれを行うには、2つの非常に簡単な方法があります。
次のように、google.appengine.api.datastoreAPIを使用します。
from google.appengine.api import datastore
q = datastore.Query('EntityType')
if q.get(1):
print "EntityType exists!"
もう1つのオプションは、db.Expandoクラスを使用することです。
def GetEntityClass(entity_type):
class Entity(db.Expando):
@classmethod
def kind(cls):
return entity_type
return Entity
cls = GetEntityClass('EntityType')
if cls.all().get():
print "EntityType exists!"
後者には、GetEntityClassを使用して任意のエンティティタイプのExpandoクラスを生成し、通常のクラスと同じように操作できるという利点があります。