【问题标题】:How to create a query for matching keys?如何创建匹配键的查询?
【发布时间】:2012-02-04 16:09:33
【问题描述】:

我使用另一个用户(赞助商)的密钥来指示谁是用户的赞助商,它会在数据存储中为那些拥有赞助商的用户创建一个链接,该链接最多可以是一个,但赞助商可以赞助许多用户喜欢在这种情况下 ID 2002 赞助了其他三个用户:

在这种情况下,此查询执行我想要的操作:SELECT * FROM User where sponsor =KEY('agtzfmJuYW5vLXd3d3ILCxIEVXNlchjSDww') 但我不知道如何使用 python 进行编程,我只能将它用于数据存储。当我想匹配在同一字段中与 key 具有相同用户的用户集时,如何通过 key 查询?我的模型中的用户最多可以有一个赞助商,我只想知道某个特定的人赞助了谁,这可能是用户列表,然后他们又赞助了我也想查询的用户。

字段赞助商是一个键,它具有指向数据存储中赞助商的链接。我像 user2.sponsor = user1.key 一样设置密钥,现在我想找到所有 user1 赞助的查询,应该就像

User.All().filter('sponsor = ', user1.key)

但是赞助商是键类型的字段,所以我不知道如何匹配它以查看例如活动用户是赞助商的人的列表,以及当第二代也有链接时它如何变成树。如何选择这个用户是赞助商的用户列表,然后是第二代?当我像 u1=u2.key 即 user2.sponsor=user1.key 一样对关系进行建模时。感谢您的任何提示

以下解决方法是不好的做法,但这是我最后也是唯一的手段:

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,)

更新

问题是 keyproperty 不是必需的,当我认为这是我的代码中的错误时,Guido Van Rossum 已将其报告为 ndb 中的错误。这是我现在正在使用的,这是一个非常可接受的解决方案,因为除了可能的程序员、测试人员和管理员之外,组织中的每个真实用户都需要拥有一个赞助商 ID,即用户 ID。

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()
    ...

【问题讨论】:

  • 我注意到你在 ndb 组中发布了这个: q2 = auth_models.User.query().filter(query.FilterNode(sponsor, '=', user.key)) 对于 Expando 查询必须引用工作赞助商,即“赞助商”
  • 非常感谢凯尔,现在我有 3 个选项。目前使用 people = auth_models.User.query(auth_models.User.sponsor == user.key).fetch() 和赞助商属性作为 KeyProperty 就像 Guido 写的那样可能更可取。使用 auth_models.User.query().filter(query.FilterNode('sponsor', '=', user.key)) 时,我在迭代时遇到 Jinja2 错误,说 ndb.key.Key 不是受支持的类型。
  • 发生了什么是你传递 jinja2 一个 query 对象而不是用户列表。在末尾添加.fetch() 以执行查询。即auth_models.User.query().filter(query.FilterNode('sponsor', '=', user.key)).fetch()
  • @Kyle Finley 感谢您修复此问题。我知道两者都应该至少可以使用错误修复:User.query().filter(query.FilterNode('sponsor', '=', user.key)).fetch()User.query(User.sponsor == user.key).fetch() 但后者要求该属性是必需的而不是动态的。

标签: google-app-engine google-cloud-datastore reference python-2.7 webapp2


【解决方案1】:

User 模型是一个 NDB Expando,查询起来有点棘手。

来自docs

另一个有用的技巧是查询 Expando 类型的动态 财产。您将无法使用 class.query(class.propname == value) 因为该类没有属性对象。相反,您可以 使用 ndb.query.FilterNode 类来构造过滤器表达式, 如下:

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()

那就试试吧:

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,)

【讨论】:

    【解决方案2】:

    选项 #2

    这个选项更简洁一些。您将模型子类化并将其位置传递给 webapp2。这将允许您向类添加自定义属性和自定义查询。

    # 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)
    

    【讨论】:

      猜你喜欢
      • 2020-11-21
      • 2011-11-02
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 2012-09-10
      • 1970-01-01
      相关资源
      最近更新 更多