【问题标题】:Flask-SQLAlchemy - Model not found when declaring relationshipFlask-SQLAlchemy - 声明关系时找不到模型
【发布时间】:2020-10-02 21:27:16
【问题描述】:

在声明我的两个模型之间的关系时(存储在两个单独的文件中,我收到以下错误:

ERROR: sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class FrequencyBand->frequency_bands_table, expression 'LicenseItem' failed to locate a name ('LicenseItem'). If this is a class name, consider adding this relationship() to the <class 'src.models.metaData.FrequencyBand'> class after both dependent classes have been defined.

我认为通过使用字符串表示(通过声明性基础)可以避免这个问题 -> 但似乎我在设置映射器之前导入了 FrequencyBand-Object。我该如何解决? (作为一种解决方法,我在 LicenseItem 上声明了关系,但我对其他关系也有类似的问题)。任何想法/提示?非常感谢任何帮助!

class FrequencyBand(db.Model):
    __tablename__ = "frequency_bands_table"
    band_id = db.Column(db.String(20), primary_key=True)
    band_nr = db.Column(db.Integer)
    name = db.Column(db.String(50))
    technology = db.Column(db.String(20))
    license = db.relationship("LicenseItem")
    license_id = db.Column(db.String(100), db.ForeignKey('license_items_table.item_id'))

class Item(db.Model):
    __tablename__ = 'items_table'
    item_id = db.Column(db.String(20), primary_key=True)
    category = db.Column(db.Enum("Antennen", "Radio", "Diverses", "Lizenzen"))
    name = db.Column(db.String(100))
    description = db.Column(db.String(100))
    otc = db.Column(db.Integer)
    mrc = db.Column(db.Integer)
    custom_price = db.Column(db.Boolean)
    item_status = db.Column(db.Enum("active", "inactive"))
    last_updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
    __mapper_args__ = {
        'polymorphic_identity':'Item',
        'polymorphic_on':category
    }
    def __str__(self):
        return self.name

class MiscellaneousItem(Item):
    __mapper_args__ = { 'polymorphic_identity':'Diverses'}
    __tablename__ = 'miscellaneous_items_table'
    item_id = db.Column(db.String(20), db.ForeignKey('items_table.item_id'), primary_key=True)

class MiscellaneousItemSchema(marshmallow.SQLAlchemyAutoSchema):
    class Meta:
        model = MiscellaneousItem
        include_fk = True

class AntennaItem(Item):
    __mapper_args__ = { 'polymorphic_identity':'Antennen'}
    __tablename__ = 'antenna_items_table'
    item_id = db.Column(db.String(20), db.ForeignKey('items_table.item_id'), primary_key=True)
    hardware_types = db.relationship("HardwareType", secondary=item_hw_type_table)
    frequency_bands = db.relationship("FrequencyBand", secondary=item_frequency_table)
    mimo_layers = db.Column(db.Integer)
    nrOfBands = db.Column(db.Integer)
    allowed_SLA_types = db.relationship("SLAType", secondary=item_sla_types_table)

class LicenseItem(Item): #Item-Subclass --> Joined table inheritance
    __mapper_args__ = { 'polymorphic_identity':'Lizenzen'}
    __tablename__ = 'license_items_table'
    item_id = db.Column(db.String(20), db.ForeignKey('items_table.item_id'), primary_key=True)
    frequencies = db.relationship("FrequencyBand", backref="license")

由于我为我的烧瓶应用程序使用命名空间和蓝图,因此模型在命名空间中导入,并且蓝图通过应用程序工厂模式注册。

from flask import Blueprint
from flask_restx import Api
from .meta_data import ns as meta_data_ns
from .projects import ns as projects_ns


api_blueprint = Blueprint('api', __name__)
api = Api(api_blueprint)

api.add_namespace(meta_data_ns, path='/meta')
api.add_namespace(projects_ns, path='/projects')
#meta namespace -> the first namespace which is registered -> and therefore the FrequencyBand is imported before LicenseItem is declared
from flask_restx import Namespace, Resource
from src.models.metaData import FrequencyBand
from src.models.item import Item, AllItemsSchema
from src.models.utils import token_required


ns = Namespace('meta', description='Operations related to meta data')

@ns.route('/')
class UnitObject(Resource):
    @token_required
    def get(self):
    #...
#app.__init__
from flask import Flask
from .extensions import db,...
from src.config import app_config


def create_app(config_name):
    """Create and return app."""
    app = Flask(__name__)
    app.config.from_object(app_config[config_name])
    db.init_app(app)
    marshmallow.init_app(app)
    ...
    with app.app_context():
        from src.api import api_blueprint
        from src.admin_backend.commands import bp as command_bp
        app.register_blueprint(api_blueprint, url_prefix="/api")
        app.register_blueprint(command_bp)
        return app

【问题讨论】:

  • 你能发布项目类吗?如果没有 Item 类,您的代码对我有用。
  • 感谢您的支持。我添加了 Item 类。我还意识到 db 引用的是 flask_sqlalchemy (而不是 sqlalchemy,但我知道这两个应该是相同的)。但是可能是 Joined table 继承导致了一些问题?

标签: python flask orm sqlalchemy flask-sqlalchemy


【解决方案1】:

FrequencyBand 类中,属性license 负责导致错误。

    license = db.relationship("LicenseItem")  # throws error

您必须删除此行并在稍后声明它,即完全按照错误消息所说的那样做。例如:

  # FrequencyBand is imported before LicenseItem is declared
  from flask_restx import Namespace, Resource
  from src.models.metaData import FrequencyBand
  from src.models.item import Item, AllItemsSchema
  from src.models.utils import token_required

  FrequencyBand.license = db.relationship("LicenseItem")

这不是一个非常优雅的解决方案,但可能适合这个特定的用例(我真的不能说)。

出现问题是因为您的类中有两个依赖关系。如果您只想声明多对多关系,请查看documentation 使用帮助表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-06
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 2018-07-24
    • 2022-01-12
    • 1970-01-01
    • 2023-03-21
    相关资源
    最近更新 更多