[Python] Unsure how to create relationships between classes within python

Discussão em 'Python' iniciado por Stack, Agosto 11, 2025.

  1. Stack

    Stack Membro Participativo

    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)

    Continue reading...

Compartilhe esta Página