0

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.

4
  • Python objects have an __dict__ attribute already, which you should not overwrite. In general avoid giving attributes names that begin and end in double-underscores; this format is used by Python to denote special attributes. Commented Feb 5, 2022 at 9:21
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a minimal reproducible example. Commented Feb 13, 2022 at 13:40
  • @snakecharmerb I honestly don't know why you would think that. Let me give you an example: class myClass: def __init__(self): self.name="My Name" This has as a native str method with output: "<__main__.myClass object at 0x000001D338C475E0>", which is not very readable. You probably don't want this in many occasions as you your default str response. Instead you may do things like overwriting it like this: class myClass2: def __init__(self): self.name="My Name" def __str__(self): return f"{self.name}" Now the return is: 'My Name' Commented Feb 15, 2022 at 9:48
  • Perhaps I didn't express it as well as I might. "Don't use "dunder" names unless you are deliberately extending their existing purpose" might have been better? __dict__ is an attribute, not a function, so converting it to a function is likely to cause problems. To get a dict of attributes you might try vars, your method with a different name or a serialisation package like marshmallow. Commented Feb 15, 2022 at 11:19

2 Answers 2

2

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 custom 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.

Sign up to request clarification or add additional context in comments.

Comments

0

I have removed __dict__, and created get_dict(self) to make my dict through the object without my constructor get problems.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.