AttributeError:'User'对象没有属性'get'-Flask-Login使用PyMongo的User类

时间:2019-04-17 14:09:53

标签: python mongodb flask pymongo flask-login

我为Flask-Login创建了一个用户类,如下所示:

 { '-LaAHp3jEK70tWB01-Go':
   { ordered_item_cost: '15',
     ordered_item_name: 'bourban-biscuits',
     ordered_item_quantity: '1',
     ordered_item_total_cost: 15,
     ordered_time: '3/17/2019, 4:26:05 PM' },
  '-LaAHsjSCNqz8VbxeMgp':
   { ordered_item_cost: '5',
     ordered_item_name: 'dark fantasy',
     ordered_item_quantity: '1',
     ordered_item_total_cost: 5,
     ordered_time: '3/17/2019, 4:26:20 PM' } }

,我有一个用户帐户路由,用户可以在其中编辑和删除其帐户。但是,要获取用户并从数据库中更新/删除,我需要使用pymongo代码:

@login_manager.user_loader
def load_user(user_id):
    users = mongo.db.users
    u = users.find_one({"_id": user_id})
    return User(u)

class User(UserMixin):

    def __init__(self, user_json):
        self.user_json = user_json

    def is_authenticated(self):
        return True

    def is_anonymous(self):
        return False

    def is_active(self):
        return True

    def get_id(self):
        object_id = self.user_json.get('_id')
        return str(object_id)

    def get_reset_token(self, expires_sec=3600):
        s = Serializer(app.config['SECRET_KEY'], expires_sec)
        id = str(self.user_json.get('_id'))
        return s.dumps({'user_id': id}).decode('utf-8')


    @staticmethod
    def verify_reset_token(token):
        s = Serializer(app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except:
            return None
        return load_user(user_id)

users = mongo.db.users
user = users.find_one({'_id': user_id})

要从数据库中获取适当的用户,并执行此操作,我需要从当前用户获取ID。 当我尝试使用current_user.get_id()时,出现以下错误:

user = users.find_one({'email': user_email})

并且如果我尝试在current_user周围投射用户(请注意current_user是flask-login属性),则会出现错误:

builtins.AttributeError
AttributeError: 'NoneType' object has no attribute 'get'

Traceback (most recent call last)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/leawhitelaw/enu_group_project/src/app_f/routes.py", line 135, in account
current_user.get_id()
File "/Users/leawhitelaw/enu_group_project/src/app_f/db_classes.py", line 29, in get_id
object_id = self.user_json.get('_id')
AttributeError: 'NoneType' object has no attribute 'get'

令人困惑的是,在get_reset_token函数中,获取_id是有效的,因为当我使用它时,该函数运行得很好。我也尝试过:

builtins.AttributeError
AttributeError: 'User' object has no attribute 'get'

Traceback (most recent call last)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/leawhitelaw/enu_group_project/src/app_f/routes.py", line 126, in account
user.get_id()
File "/Users/leawhitelaw/enu_group_project/src/app_f/db_classes.py", line 29, in get_id
object_id = self.user_json.get('_id')
File "/usr/local/lib/python3.7/site-packages/werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
AttributeError: 'User' object has no attribute 'get'

,其中得到NoneType不可下标或User type不可下标。

我知道User对象与数据库中的用户不同,但是我需要从current_user获取一些信息才能将其连接到数据库中的相应用户。

1 个答案:

答案 0 :(得分:1)

默认情况下,此处的User类没有get()方法,也没有实现支持__getitem__()或类似访问模式所必需的user["email"]方法,这是导致错误的根本原因

get_reset_token()的调用之所以有效,是因为它对self.user_json.get('_id'))进行了调用,其中user_json是包装的字典,它确实支持get和subscribeable访问。

可能的解决方案:

1。代理get和__getitem__到包装好的字典

这是部分解决方案,还有其他一些魔术方法可以实现,以使用户的行为更像字典,但这是一个起点。

class User(UserMixin):
  ...
  def get(self, key):
    return self.user_json.get(key)

  def __getitem__(self, key):
    return self.user_json[key]

  def __setitem__(self, key, value):
    return self.user_json[key] = value

  def __delitem__(self, key):
    del self.user_json[key]
  ...

2。为特定的访问模式创建属性

get_email()之类的getter方法相比,属性更具Python风格。

class User(UserMixin):
  ...
  @property
  def email(self):
    return self.user_json["email"]

  @email.setter
  def email(self, value):
    self.user_json["email"] = value
  ...