在SQLAlchemy中配置继承时出错

时间:2016-02-18 22:12:03

标签: python flask sqlalchemy flask-sqlalchemy

我正在尝试将某些模型重构为Joined Table Inheritance。我能够让配置在我们的模型库中工作,但是我们的API在类似模型上没有取得任何成功。我收到的错误发生在Flask应用程序尝试以任何形式与模型交互的那一刻,而不仅仅是继承表。

Stacktrace

Traceback (most recent call last):
  File ".../lib/python3.5/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File ".../lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File ".../lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
    return original_handler(e)
  File ".../lib/python3.5/site-packages/flask_cors/extension.py", line 110, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File ".../lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File ".../lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File ".../lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File ".../lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File ".../lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
    return original_handler(e)
  File ".../lib/python3.5/site-packages/flask_cors/extension.py", line 110, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File ".../lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File ".../lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File ".../lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File ".../lib/python3.5/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File ".../app/views/views.py", line 177, in test
    vehicles = Vehicle.query.all()
  File ".../lib/python3.5/site-packages/flask_sqlalchemy/__init__.py", line 452, in __get__
    mapper = orm.class_mapper(type)
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/base.py", line 421, in class_mapper
    mapper = _inspect_mapped_class(class_, configure=configure)
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/base.py", line 400, in _inspect_mapped_class
    mapper._configure_all()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/mapper.py", line 1167, in _configure_all
    configure_mappers()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/mapper.py", line 2688, in configure_mappers
    mapper._post_configure_properties()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/mapper.py", line 1710, in _post_configure_properties
    prop.init()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/interfaces.py", line 183, in init
    self.do_init()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/relationships.py", line 1617, in do_init
    self._setup_join_conditions()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/relationships.py", line 1692, in _setup_join_conditions
    can_be_synced_fn=self._columns_are_mapped
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/relationships.py", line 1960, in __init__
    self._determine_joins()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/relationships.py", line 2043, in _determine_joins
    consider_as_foreign_keys=consider_as_foreign_keys
  File "<string>", line 2, in join_condition

  File ".../lib/python3.5/site-packages/sqlalchemy/sql/selectable.py", line 824, in _join_condition
    a, a_subset, b, consider_as_foreign_keys)
  File ".../lib/python3.5/site-packages/sqlalchemy/sql/selectable.py", line 881, in _joincond_scan_left_right
    if nrte.table_name == b.name:
AttributeError: 'Join' object has no attribute 'name'

Stacktrace 2

Traceback (most recent call last):
  File ".../lib/python3.5/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File ".../lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File ".../lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
    return original_handler(e)
  File ".../lib/python3.5/site-packages/flask_cors/extension.py", line 110, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File ".../lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File ".../lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File ".../lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File ".../lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File ".../lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
    return original_handler(e)
  File ".../lib/python3.5/site-packages/flask_cors/extension.py", line 110, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File ".../lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File ".../lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File ".../lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File ".../lib/python3.5/site-packages/flask/app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File ".../app/views/views.py", line 177, in test
    vehicles = TrackingIncidentType.query.all()
  File ".../lib/python3.5/site-packages/flask_sqlalchemy/__init__.py", line 452, in __get__
    mapper = orm.class_mapper(type)
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/base.py", line 421, in class_mapper
    mapper = _inspect_mapped_class(class_, configure=configure)
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/base.py", line 400, in _inspect_mapped_class
    mapper._configure_all()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/mapper.py", line 1167, in _configure_all
    configure_mappers()
  File ".../lib/python3.5/site-packages/sqlalchemy/orm/mapper.py", line 2685, in configure_mappers
    raise e
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.  Original exception was: 'Join' object has no attribute 'name'

模型

class Asset(db.Model):
    __tablename__ = 'assets'

    asset_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    asset_type_id = db.Column(db.ForeignKey('asset_types.asset_type_id'))
    ...

    __mapper_args__ = {
        'polymorphic_on': asset_type_id
    }


class Equipment(Asset):
    __tablename__ = 'equipment'

    asset_id = db.Column(db.ForeignKey('assets.asset_id'), primary_key=True)
    ...
    ...
    __mapper_args__ = {
        'polymorphic_identity':1
    }


class Vehicle(Asset):
    __tablename__ = 'vehicles'

    asset_id = db.Column(db.ForeignKey('assets.asset_id'), primary_key=True)
    ...
    ...
    __mapper_args__ = {
        'polymorphic_identity':2
    }

资产类型

db=# select * from asset_types;
 asset_type_id |   name
---------------+-----------
             1 | equipment
             2 | vehicle
(2 rows)

1 个答案:

答案 0 :(得分:0)

不幸的是我无法发布与此问题相关的所有代码(数千行模型),但无论如何我都会尝试解释答案......

我正在将两个表(车辆和设备)重构为连接继承层次结构。部分重构是从表中删除vehicles.vehicle_idequipment.equipment_id主键。因此,我不得不更改模型中的所有外键列(即equipment_id = db.Column(db.ForeignKey('equipment.equipment_id')))。在将模型分解为一个独立的项目之后,我意识到在我的应用程序中有一个意外的地方有一个模型,并且它没有被重构为新的FK。这导致了神秘的错误。

所以有些代码希望清除这一点:

重构前的模型

class TrackingEvent(db.Model):
    __tablename__ = 'tracking_events'

    tracking_event_id = db.Column(db.Integer, primary_key=True)
    equipment_id = db.Column(db.ForeignKey('equipment.equipment_id'))

注意:模型或数据库中不再存在引用的equipment.equipment_id

重构后的模型

class TrackingEvent(db.Model):
    __tablename__ = 'tracking_events'

    tracking_event_id = db.Column(db.Integer, primary_key=True)
    asset_id = db.Column(db.ForeignKey('assets.asset_id'))