如何创建匹配键的查询?

发布于 2024-12-25 21:35:24 字数 2404 浏览 1 评论 0原文

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

在此处输入图像描述

在这种情况下,此查询执行我想要的操作:<代码>从用户中选择* where grant =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()
    ...

I use the key of another User, the sponsor, to indicate who is the sponsor of a User and it creates a link in the datastore for those Users that have a sponsor and it can be at most one but a sponsor can sponsor many users like in this case ID 2002 who sponsored three other users:

enter image description here

In this case this query does what I want: SELECT * FROM User where sponsor =KEY('agtzfmJuYW5vLXd3d3ILCxIEVXNlchjSDww') but I don't know how to program that with python, I can only use it to the datastore. How can I query by key when I want to match the set of users who has the same user as key in the same field? A user in my model can have at most one sponsor and I just want to know who a particular person sponsored which could be a list of users and then they sponsored users in their turn which I also want to query on.

The field sponsor is a key and it has a link to the sponsor in the datastore. I set the key just like user2.sponsor = user1.key and now I want to find all that user1 sponsored with a query that should be just like

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

but sponsor is a field of type key so I don't know how to match it to see for example a list a people the active user is a sponsor for and how it becomes a tree when the second generation also have links. How to select the list of users this user is a sponsor for and then the second generation? When i modelled the relation simply like u1=u2.key ie user2.sponsor=user1.key. Thanks for any hint

The following workaround is bad practice but is my last and only resort:

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

Update

The issues are that the keyproperty is not required and that Guido Van Rossum has reported this as a bug in the ndb when I think it's a bug in my code. Here's what I'm using now, which is a very acceptable solution since every real user in the organization except possibly programmers, testers and admins are going the be required to have a sponsor ID which is a user 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()
    ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无所的.畏惧 2025-01-01 21:35:24

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

来自文档

另一个有用的技巧是查询 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,)

The User model is an NDB Expando which is a little bit tricky to query.

From the docs

Another useful trick is querying an Expando kind for a dynamic
property. You won't be able to use class.query(class.propname ==
value) as the class doesn't have a property object. Instead, you can
use the ndb.query.FilterNode class to construct a filter expression,
as follows:

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

So try:

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,)
轮廓§ 2025-01-01 21:35:24

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

Option #2

This option is a little bit cleaner. You subclass the model and pass it's location to webapp2. This will allow you to add custom attributes and custom queries to the class.

# 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文