google-app-engine - gae - google app engine tutorial español
¿Cómo crear una consulta para hacer coincidir claves? (2)
El modelo de usuario es un NDB Expando que es un poco difícil de consultar.
De los documentos
Otro truco útil es consultar un tipo Expando para una propiedad dinámica. No podrá usar class.query (class.propname == value) ya que la clase no tiene un objeto de propiedad. En su lugar, puede usar la clase ndb.query.FilterNode para construir una expresión de filtro, de la siguiente manera:
from ndb import model, query
class X(model.Expando):
@classmethod
def query_for(cls, name, value):
return cls.query(query.FilterNode(name, ''='', value))
print X.query_for(''blah'', 42).fetch()
Así que prueba:
form ndb import query
def get(self):
auser = self.auth.get_user_by_session()
realuser = auth_models.User.get_by_id(long( auser[''user_id''] ))
people = auth_models.User.query(query.FilterNode(''sponsor'', ''='', realuser.key)).fetch()
if auser:
self.render_jinja(''my_organization.html'', people=people, user=realuser,)
Utilizo la clave de otro Usuario, el patrocinador, para indicar quién es el patrocinador de un Usuario y crea un enlace en el almacén de datos para aquellos Usuarios que tienen un patrocinador y puede ser como máximo uno, pero un patrocinador puede patrocinar a muchos usuarios como en este caso, ID 2002 que patrocinó a otros tres usuarios:
En este caso, esta consulta hace lo que quiero: SELECT * FROM User where sponsor =KEY(''agtzfmJuYW5vLXd3d3ILCxIEVXNlchjSDww'')
pero no sé cómo programar eso con python, solo puedo usarlo en el almacén de datos. ¿Cómo puedo consultar por clave cuando quiero hacer coincidir el conjunto de usuarios que tiene el mismo usuario como clave en el mismo campo? Un usuario en mi modelo puede tener como máximo un patrocinador y solo quiero saber quién patrocinó una persona en particular, que podría ser una lista de usuarios y luego, a su vez, patrocinaron a los usuarios que también desean consultar.
El patrocinador de campo es una clave y tiene un enlace al patrocinador en el almacén de datos. Configuré la clave como user2.sponsor = user1.key y ahora quiero encontrar todo ese user1 patrocinado con una consulta que debería ser como
User.All().filter(''sponsor = '', user1.key)
pero el patrocinador es un campo de clave de tipo, por lo que no sé cómo emparejarlo para ver, por ejemplo, una lista de personas a las que el usuario activo es patrocinador y cómo se convierte en un árbol cuando la segunda generación también tiene enlaces. ¿Cómo seleccionar la lista de usuarios para los que este usuario es patrocinador y luego la segunda generación? Cuando modelé la relación simplemente como u1 = u2.key ie user2.sponsor = user1.key. Gracias por cualquier pista
La siguiente solución alternativa es una mala práctica pero es mi último y único recurso:
def get(self):
auser = self.auth.get_user_by_session()
realuser = auth_models.User.get_by_id(long( auser[''user_id''] ))
q = auth_models.User.query()
people = []
for p in q:
try:
if p.sponsor == realuser.key:
people.append(p)
except Exception, e:
pass
if auser:
self.render_jinja(''my_organization.html'', people=people, user=realuser,)
Actualizar
El problema es que la propiedad clave no es necesaria y que Guido Van Rossum ha informado de esto como un error en el ndb cuando creo que es un error en mi código. Esto es lo que estoy usando ahora, que es una solución muy aceptable ya que cada usuario real en la organización, excepto posiblemente los programadores, probadores y administradores, deben tener una identificación de patrocinador que sea una identificación de usuario.
from ndb import query
class Myorg(NewBaseHandler):
@user_required
def get(self):
user = auth_models.User.get_by_id(long(self.auth.get_user_by_session()[''user_id'']))
people = auth_models.User.query(auth_models.User.sponsor == user.key).fetch()
self.render_jinja(''my_organization.html'', people=people,
user=user)
class User(model.Expando):
"""Stores user authentication credentials or authorization ids."""
#: The model used to ensure uniqueness.
unique_model = Unique
#: The model used to store tokens.
token_model = UserToken
sponsor = KeyProperty()
created = model.DateTimeProperty(auto_now_add=True)
updated = model.DateTimeProperty(auto_now=True)
# ID for third party authentication, e.g. ''google:username''. UNIQUE.
auth_ids = model.StringProperty(repeated=True)
# Hashed password. Not required because third party authentication
# doesn''t use password.
password = model.StringProperty()
...
Opcion 2
Esta opción es un poco más limpia. Usted subclasifica el modelo y pasa su ubicación a webapp2. Esto le permitirá agregar atributos personalizados y consultas personalizadas a la clase.
# custom_models.py
from webapp2_extras.appengine.auth.models import User
from google.appengine.ext.ndb import model
class CustomUser(User):
sponsor = model.KeyProperty()
@classmethod
def get_by_sponsor_key(cls, sponsor):
# How you handle this is up to you. You can return a query
# object as shown, or you could return the results.
return cls.query(cls.sponsor == sponsor)
# handlers.py
def get(self):
auser = self.auth.get_user_by_session()
realuser = custom_models.CustomUser.get_by_id(long( auser[''user_id''] ))
people = custom_models.CustomUser.get_by_sponsor_key(realuser.key).fetch()
if auser:
self.render_jinja(''my_organization.html'', people=people, user=realuser,)
# main.py
config = {
# ...
''webapp2_extras.auth'': {
# Tell webapp2 where it can find your CustomUser
''user_model'': ''custom_models.CustomUser'',
},
}
application = webapp2.WSGIApplication(routes, config=config)