简体   繁体   中英

"AttributeError: 'function' object has no attribute 'get'" in SQLAlchemy ORM Object contructor - Flask

EDIT Found my error, Leaving problem description as is. but appending answer bellow.

In my registration function, I want to create a new User object. I've defined a User Table like this:

class User(_USERDB.Model, UserMixin):
    """
    User defining Data
    """
    __tablename__ = "users"
    __table_args__ = {'extend_existing': True}
    id = Column(Integer, primary_key=True)
    mail = Column(Text, unique=True, nullable=False)
    pw = Column(Text, nullable=False)
    date_of_creation = Column(DateTime(timezone=True), default=datetime.now)  # the date the user is created
    settings = relationship("UserSettingProfile", back_populates="user", passive_deletes=True)
    admin = Column(Boolean, default=False, nullable=False)
    world_id = Column(Integer, nullable=True)

    def __dict__(self):
        return {
            "id": self.id,
            "mail": self.mail,
            "date_of_creation": self.date_of_creation,
            "admin": self.admin,
            "world_id": self.world_id
        }

If I now use the constructor as in other tutorials (TechWithTim - Flask Bog tutorial)

new_user = User(mail=mail, pw=pw_hash, admin=admin)

I get the error from the Title "AttributeError: 'function' object has no attribute 'get'"

I've already tried stepping through the debugger to spot where this comes from, but it's not much more helpful than the stack trace. All I did was validate that the stack trace, is the stack trace (not very helpful indeed)

Traceback (most recent call last):
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 2091, in __call__
    return self.wsgi_app(environ, start_response)
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 2076, in wsgi_app
    response = self.handle_exception(e)
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 2073, in wsgi_app
    response = self.full_dispatch_request()
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
    rv = self.dispatch_request()
  File "E:\project\venv\Lib\site-packages\flask\app.py", line 1502, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "E:\project\web_interface\routes\api_routing.py", line 135, in register
    new_user = User(mail=mail, pw=pw_hash, admin=admin)
  File "<string>", line 4, in __init__
    
  File "E:\project\venv\Lib\site-packages\sqlalchemy\orm\state.py", line 479, in _initialize_instance
    with util.safe_reraise():
  File "E:\project\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 70, in __exit__
    compat.raise_(
  File "E:\project\venv\Lib\site-packages\sqlalchemy\util\compat.py", line 207, in raise_
    raise exception
  File "E:\project\venv\Lib\site-packages\sqlalchemy\orm\state.py", line 477, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "E:\project\venv\Lib\site-packages\sqlalchemy\orm\decl_base.py", line 1157, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "E:\project\venv\Lib\site-packages\sqlalchemy\orm\attributes.py", line 459, in __set__
    self.impl.set(
  File "E:\project\venv\Lib\site-packages\sqlalchemy\orm\attributes.py", line 1094, in set
    old = dict_.get(self.key, NO_VALUE)
AttributeError: 'function' object has no attribute 'get'

For completion's sake, here is my api_routing.py file:

from flask import Blueprint, request, jsonify
from database import User, UserSettingProfile

@api_routes.route("/register", methods=["POST"])
def register():

    response = {"message": ""}

    try:
        mail = request.values["mail"]
        pw1 = request.values["pw1"]
        pw2 = request.values["pw2"]

    except KeyError as e:
        response["message"] = f"{e=} | Missing argument. Expected: mail, password1, password2"
        return jsonify(response), 400

    admin = False

    pw_hash = hash_pw(pw1)
    print(f"{pw_hash=}\n{mail=}\n{admin=}")
    new_user = User(mail=mail, pw=pw_hash, admin=admin)
    print(new_user)
    new_user_settings = UserSettingProfile(user_id=new_user.id)

    _USERDB.session.add(new_user)
    _USERDB.session.add(new_user_settings)
    _USERDB.session.commit()

    login_user(new_user, remember=True)
    response["message"] = f"{mail=} registered and logged in successfully"
    return jsonify(response), 200

All the parameters that I pass on into the User() constructor are valid and as expected:

pw_hash='$2b$14$6UpznQzJgw/zLZLGmjBkfOpm.D8iGXf/OsfqRkAVyzcZFM88kdos2'
mail='test_mail'
admin=False

After looking at other posts, I double-checked: The name "User" in the namespace indeed maps to the model-class I defined.

Answer The reason it fails is thanks to the __dict__ method. Since the removal of it, everything works fine.

Of course this leads to the next question: How to define costume dict functions for those classes

I couldn't find an answer to this but still want to offer a solution: Define a custom function that takes the required obj as a parameter and then puts the wanted fields into a dict. Not the most elegant solution IMO but it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM