The classes works when separate, now, I want to create relationships between them. However, this has caused issues when I am trying to define the relationships.
For example:
sqlalchemy.exc.ArgumentError: relationship 'transactions' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)
I've also had problems with the error 'users is not defined' from the line
user: db.Mapped['users'] = db.relationship(back_populates='portfolio_entries')
Here is the Transactions and PortfolioEntry class within models.py within the trading folder:
from .. import db
from datetime import datetime
from sqlalchemy.sql import func
class Transaction(db.Model):
__tablename__ = 'transactions'
id: db.Mapped[int] = db.mapped_column(db.Integer, primary_key=True)
date_created: db.Mapped[datetime] = db.mapped_column(
db.DateTime(timezone=True),
nullable=False,
server_default=func.now()
)
symbol: db.Mapped[str] = db.mapped_column(db.String(10), nullable=False)
shares: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False, default=0)
price: db.Mapped[float] = db.mapped_column(db.Float, nullable=False, default=0.0)
transaction_type: db.Mapped[str] = db.mapped_column(db.String(4), nullable=False)
user_id: db.Mapped[int]= db.mapped_column(db.Integer, db.ForeignKey('users.id'), nullable=False)
user: db.Mapped['users'] = db.relationship(back_populates='transactions')
@property
def cost(self):
return abs(self.shares * self.price)
class PortfolioEntry(db.Model):
__tablename__ = 'portfolio_entries'
id: db.Mapped[int] = db.mapped_column(db.Integer, primary_key=True)
symbol: db.Mapped[str] = db.mapped_column(db.String(10), nullable=False)
shares: db.Mapped[int] = db.mapped_column(db.Integer, nullable=False)
cost: db.Mapped[float] = db.mapped_column(db.Float, nullable=False)
price: db.Mapped[float] = db.mapped_column(db.Float, nullable=False)
user_id: db.Mapped[int] = db.mapped_column(db.Integer, db.ForeignKey('users.id'), nullable=False)
user: db.Mapped['users'] = db.relationship(back_populates='portfolio_entries')
@property
def value(self) -> float:
return self.shares * self.price
@property
def gain(self) -> float:
return self.value - self.cost
Here is the Users class within models.py within the Users folder:
from .. import db
from flask_bcrypt import (
generate_password_hash,
check_password_hash
)
from flask_login import UserMixin
from typing import List
class User(db.Model, UserMixin):
__tablename__ = 'users'
id: db.Mapped[int] = db.mapped_column(db.Integer, primary_key=True)
username: db.Mapped[str] = db.mapped_column(db.String(15), nullable=False)
email: db.Mapped[str] = db.mapped_column(db.String(320), unique=True)
password_hash: db.Mapped[str] = db.mapped_column(db.String(60), nullable=False)
transactions: db.Mapped[List['transactions']] = db.relationship(back_populates='users')
portfolio_entries: db.Mapped[List['portfolio_entries']] = db.relationship(back_populates='users')
@property
def password(self):
raise AttributeError('writeonly attr: password')
@password.setter
def password(self, value):
self.password_hash = generate_password_hash(value)
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
Full error messages:
Traceback (most recent call last):
File "/workspaces/stockx/bin/flask", line 8, in <module>
sys.exit(main())
^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 1131, in main
cli.main()
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1363, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1830, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1226, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 794, in invoke
return callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/decorators.py", line 93, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 794, in invoke
return callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 979, in run_command
raise e from None
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 963, in run_command
app: WSGIApplication = info.load_app() # pyright: ignore
^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 349, in load_app
app = locate_app(import_name, name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 264, in locate_app
return find_app_by_string(module, app_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 178, in find_app_by_string
app = attr(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/src/stockx/__init__.py", line 29, in create_app
user = User(
^^^^^
File "<string>", line 4, in __init__
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/state.py", line 566, in _initialize_instance
manager.dispatch.init(self, args, kwargs)
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/event/attr.py", line 497, in __call__
fn(*args, **kw)
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 4410, in _event_on_init
instrumenting_mapper._check_configure()
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 2401, in _check_configure
_configure_registries({self.registry}, cascade=True)
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 4218, in _configure_registries
_do_configure_registries(registries, cascade)
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 4259, in _do_configure_registries
mapper._post_configure_properties()
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/mapper.py", line 2418, in _post_configure_properties
prop.init()
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/interfaces.py", line 595, in init
self.do_init()
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/relationships.py", line 1655, in do_init
self._setup_entity()
File "/workspaces/stockx/lib/python3.12/site-packages/sqlalchemy/orm/relationships.py", line 1885, in _setup_entity
raise sa_exc.ArgumentError(
sqlalchemy.exc.ArgumentError: relationship 'transactions' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)
Even when I change users (tablename) to User (class name) I still receive the issue that User is undefined. Regardless of whether or not I import the class (from stockx.trading.models import Transaction)
Full error:
Traceback (most recent call last):
File "/workspaces/stockx/bin/flask", line 8, in <module>
sys.exit(main())
^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 1131, in main
cli.main()
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1363, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1830, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 1226, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 794, in invoke
return callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/decorators.py", line 93, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/click/core.py", line 794, in invoke
return callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 979, in run_command
raise e from None
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 963, in run_command
app: WSGIApplication = info.load_app() # pyright: ignore
^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 349, in load_app
app = locate_app(import_name, name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 264, in locate_app
return find_app_by_string(module, app_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/lib/python3.12/site-packages/flask/cli.py", line 178, in find_app_by_string
app = attr(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/stockx/src/stockx/__init__.py", line 24, in create_app
from .users.models import User
File "/workspaces/stockx/src/stockx/users/__init__.py", line 2, in <module>
from .models import User
File "/workspaces/stockx/src/stockx/users/models.py", line 8, in <module>
from stockx.trading.models import Transaction
File "/workspaces/stockx/src/stockx/trading/models.py", line 4, in <module>
from stockx.users.models import User
ImportError: cannot import name 'User' from partially initialized module 'stockx.users.models' (most likely due to a circular import) (/workspaces/stockx/src/stockx/users/models.py)