Sins97
Sins97

Reputation: 387

I'm getting raise AttributeError(key) error in Flask

In flask, I'm using marshmallow_sqlalchemy package to serialize and de-serialize model data. I have two models, Account and Address. I have Account foreign key to Address model. My model details are listed below.

models.py

class Account(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(length=30), nullable=False)
    username = db.Column(db.String(length=15), nullable=False, unique=True)
    email = db.Column(db.String(length=100), nullable=False, unique=True)
    password = db.Column(db.String(), nullable=False)
    image = db.Column(db.String())
    address = db.relationship(
        "Address",
        cascade="all, delete, delete-orphan",
        backref="account",
        lazy=True,
    )


class AccountSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = Account
        exclude = ["password"]
        include_relationships = True
        load_instance = True
class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    address = db.Column(db.Text)
    phone = db.Column(db.Integer)
    city = db.Column(db.String(length=35))
    state = db.Column(db.String(length=25))
    account_id = db.Column(db.Integer, db.ForeignKey("account.id"), nullable=False)


class AddressSchema(SQLAlchemyAutoSchema):
    class Meta:
        model = Address
        include_fk = True
        load_instance = True

So here I have two schemas created also, so when I try to run the app and create database i get this error

Traceback (most recent call last):
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/flask/cli.py", line 897, in run_command
    app = info.load_app()
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/flask/cli.py", line 308, in load_app
    app = locate_app(import_name, name)
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/flask/cli.py", line 218, in locate_app
    __import__(module_name)
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/app.py", line 1, in <module>
    from flaskproject import create_app
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/flaskproject/__init__.py", line 4, in <module>
    from flaskproject.database import load_database
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/flaskproject/database.py", line 7, in <module>
    from .user import models
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/flaskproject/user/__init__.py", line 1, in <module>
    from . import views
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/flaskproject/user/views.py", line 10, in <module>
    from .models import Account, AccountSchema
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/flaskproject/user/models.py", line 62, in <module>
    class AccountSchema(SQLAlchemyAutoSchema):
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow/schema.py", line 121, in __new__
    klass._declared_fields = mcs.get_declared_fields(
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow_sqlalchemy/schema.py", line 91, in get_declared_fields
    fields.update(mcs.get_declared_sqla_fields(fields, converter, opts, dict_cls))
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow_sqlalchemy/schema.py", line 130, in get_declared_sqla_fields
    converter.fields_for_model(
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow_sqlalchemy/convert.py", line 154, in fields_for_model
    field = base_fields.get(key) or self.property2field(prop)
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow_sqlalchemy/convert.py", line 193, in property2field
    field_class = field_class or self._get_field_class_for_property(prop)
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/marshmallow_sqlalchemy/convert.py", line 275, in _get_field_class_for_property
    column = _base_column(prop.columns[0])
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 1329, in __getattr__
    return self._fallback_getattr(key)
  File "/home/jackson/Learning/Python/flask-learning/FlaskLearn02/env007/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 1298, in _fallback_getattr
    raise AttributeError(key)
AttributeError: columns

I'm unable to find the solution for it, but one thing I understood lately is that the schemas I have created is causing the issue because when I comment out the AccountSchema there is no error at all. I can't seem to understand why. Please help me on this

Upvotes: -1

Views: 677

Answers (1)

Timilehin Aliyu
Timilehin Aliyu

Reputation: 1

It seems that the error you are getting is because the Address class is not yet defined when the Account class is being defined. Therefore, the backref argument in the account relationship of the Address class cannot be resolved.

To fix this, you can define the Address class before the Account class in your code

class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
address = db.Column(db.Text)
phone = db.Column(db.Integer)
city = db.Column(db.String(length=35))
state = db.Column(db.String(length=25))
account_id = db.Column(db.Integer, db.ForeignKey("account.id"), nullable=False)

account = db.relationship(
    "Account",
    backref="address",
    lazy=True,
)

class Account(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(length=30), nullable=False)
username = db.Column(db.String(length=15), nullable=False, unique=True)
email = db.Column(db.String(length=100), nullable=False, unique=True)
password = db.Column(db.String(), nullable=False)
image = db.Column(db.String())

class AccountSchema(SQLAlchemyAutoSchema):
    class Meta:
    model = Account
    exclude = ["password"]
    include_relationships = True
    load_instance = True


class AddressSchema(SQLAlchemyAutoSchema):
   class Meta:
      model = Address
      include_fk = True
      load_instance = True

this updated code, the account relationship is defined inside the Address class after the account_id column is defined.

Upvotes: 0

Related Questions