Как динамически определить, существует ли класс модели в Google App Engine?
-
09-09-2019 - |
Вопрос
Я хочу иметь возможность взять динамически созданную строку, скажем «Pigeon», и определить во время выполнения, есть ли в Google App Engine определенный в этом проекте класс модели с именем «Pigeon».Если «Голубь» — это имя существующего класса модели, я хотел бы затем получить ссылку на определенный таким образом класс Pigeon.
Кроме того, я вообще не хочу использовать eval, поскольку динамическая строка «Голубь» в данном случае приходит извне.
Решение
Есть два довольно простых способа сделать это, не полагаясь на внутренние детали:
Используйте API google.appengine.api.datastore, например:
from google.appengine.api import datastore
q = datastore.Query('EntityType')
if q.get(1):
print "EntityType exists!"
Другой вариант — использовать класс 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 для любого типа сущности и взаимодействовать с ним так же, как с обычным классом.
Другие советы
Вы можете попробовать, хотя, вероятно, это очень и очень плохая практика:
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
РЕДАКТИРОВАТЬ 2:Да, это работает!Ву!
На самом деле, просматривая исходный код и Интернет, я нашел недокументированный метод, который, кажется, отвечает всем требованиям.
from google.appengine.ext import db
key = "ModelObject" #This is a dynamically generated string
klass = db.class_for_kind(key)
Этот метод выдаст описательное исключение, если класс не существует, поэтому вам, вероятно, следует его перехватить, если строка ключа поступает извне.