Domanda

Voglio essere in grado di prendere una stringa creata dinamicamente, dire "Piccione" e determinare in fase di esecuzione se Google App Engine ha una classe modello definito in questo progetto denominato "Piccione". Se "piccione" è il nome di una classe del modello inesistente, vorrei quindi ottenere un riferimento alla classe Pigeon così definita.

Inoltre, non voglio usare eval a tutti, dal momento che la stringa dinamica "Pigeon" in questo caso, viene da fuori.

È stato utile?

Soluzione

Ci sono due semplici modi abbastanza per fare questo senza fare affidamento su dettagli interni:

Utilizzare l'API google.appengine.api.datastore, in questo modo:

from google.appengine.api import datastore

q = datastore.Query('EntityType')
if q.get(1):
  print "EntityType exists!"

L'altra opzione è quella di utilizzare la classe 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!"

Quest'ultimo ha il vantaggio che è possibile utilizzare GetEntityClass per generare una classe Expando per qualsiasi tipo di entità, e interagire con esso allo stesso modo si farebbe una classe normale.

Altri suggerimenti

Si potrebbe provare, anche se probabilmente molto, molto cattiva pratica:

def get_class_instance(nm) :
    try :
        return eval(nm+'()')
    except :
        return None

Inoltre, per rendere più sicuro che, si potrebbe dare eval un hash locali: eval(nm+'()', {'Pigeon':pigeon})

Non sono sicuro se questo avrebbe funzionato, e ha sicuramente un problema: se c'è una funzione chiamata il valore di nm, che sarebbe tornato che:

def Pigeon() :
    return "Pigeon"
print(get_class_instance('Pigeon')) # >> 'Pigeon'

Modifica : Un altro modo di farlo è forse (non testato), se si conosce il modulo:
(Sorry, continuo a dimenticare che non è obj.hasattr, la sua hasattr (obj)!)

import models as m
def get_class_instance(nm) :
    if hasattr(m, nm) :
        return getattr(m, nm)()
    else : return None

Modifica 2 : Sì, funziona! Woo!

In realtà, guardando attraverso il codice sorgente e interweb, ho trovato un metodo non documentato che sembra adattarsi il disegno di legge.

from google.appengine.ext import db

key = "ModelObject" #This is a dynamically generated string

klass = db.class_for_kind(key)

Questo metodo un'eccezione descrittiva se la classe non esiste, quindi probabilmente si dovrebbe prenderlo se la stringa chiave proviene dall'esterno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top