【问题标题】:SQLAlchemy has maximum number of relationships?SQLAlchemy 有最大数量的关系?
【发布时间】:2020-01-18 22:07:36
【问题描述】:

我正在使用 python 3.6 和 SQLAlchemy 1.3.8,我遇到了一个有点陌生的问题...我收到了多个关系的相同异常(24 个类通过多种类型的关系相互关联) 并且每次运行脚本时都会发生相同的问题,但表不同。当班级数量少于二十个时,我没有面对它……那么,是否有可能存在最大数量的关系?

回溯是:

Traceback (most recent call last):
  File "yaml_parser.py", line 70, in <module>
    Base.metadata.create_all()
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 4294, in create_all
    ddl.SchemaGenerator, self, checkfirst=checkfirst, tables=tables
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 2046, in _run_visitor
    conn._run_visitor(visitorcallable, element, **kwargs)
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1615, in _run_visitor
    visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/visitors.py", line 132, in traverse_single
    return meth(obj, **kw)
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/ddl.py", line 754, in visit_metadata
    [t for t in tables if self._can_create_table(t)]
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/ddl.py", line 1158, in sort_tables_and_constraints
    dependent_on = fkc.referred_table
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 3218, in referred_table
    return self.elements[0].column.table
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 855, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/home/jarvis/venv/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 2025, in column
    tablekey,
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'model.<foreing_key_column>' could not find table '<table_name>' with which to generate a foreign key to target column 'id'

要重现,请使用以下脚本

base.py

#!/usr/bin/python3
import uuid
from sqlalchemy.dialects.mysql.base import MSBinary
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import String, Column, Integer, types
import re


def generate_uuid():
    return str(uuid.uuid4())


def camel2snake(string):
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', string)
    result = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
    return result


class UUID(types.TypeDecorator):
    impl = MSBinary

    def __init__(self):
        self.impl.length = 16
        types.TypeDecorator.__init__(self, length=self.impl.length)

    def process_bind_param(self, value, dialect=None):
        if value and isinstance(value, uuid.UUID):
            return value.bytes
        elif value and not isinstance(value, uuid.UUID):
            raise ValueError('value %s is not a valid uuid.UUID' % value)
        else:
            return None

    def process_result_value(self, value, dialect=None):
        if value:
            return uuid.UUID(bytes=value)
        else:
            return None

    def is_mutable(self):
        return False


class NBase(object):
    __tablename__ = camel2snake(__name__)
    __table_args__ = {'extend_existing': True}
    id = Column(UUID, primary_key=True, default=generate_uuid())


Base = declarative_base(cls=NBase)


class Timeframe(Base):
    """docstring for Timeframe"""
    __tablename__ = camel2snake(__name__)
    day = Column(Integer)
    timestamp = Column(String)

model.py

#!/usr/bin/python3
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, reconstructor
from sqlalchemy import (
    Column, Integer, String, Boolean, ForeignKey, Enum, Text
)
from base import camel2snake, Base, Timeframe, UUID


class SliceObject(Base):
    """docstring for Slice"""
    __tablename__ = camel2snake(__name__)
    # One-to-one relationship with SliceConstraints class
    slice_constraints = relationship(
        "SliceConstraints", uselist=False,
        back_populates="slice_object")
    # One-to-one relationship with SliceRequirements class
    slice_requirements = relationship(
        "SliceRequirements", uselist=False,
        back_populates="slice_object")
    # One-to-one relationship with SliceLifecycle class
    slice_lifecycle = relationship(
        "SliceLifecycle", uselist=False, back_populates="slice_object")
    # One-to-one relationship with SliceCost class
    cost = relationship(
        "SliceCost", uselist=False, back_populates="slice_object")
    # One-to-one relationship with SliceTimeframe class
    slice_timeframe = relationship(
        "SliceTimeframe", uselist=False, back_populates="slice_object")
    # One-to-many relationship with ServiceDescription class
    service_description_id = Column(
        UUID, ForeignKey(camel2snake("ServiceDescription") + ".id"))
    service_description = relationship("ServiceDescription")
    # One-to-many relationship with SliceDescription class
    slice_description_id = Column(
        UUID, ForeignKey(camel2snake("SliceDescription") + ".id"))
    slice_description = relationship("SliceDescription")


class SliceConstraints(Base):
    """docstring for SliceConstraints"""
    __tablename__ = camel2snake(__name__)
    # One-to-one relationship with Geographic class
    geographic = relationship(
        "Geographic", uselist=False, back_populates="slice_constraints")
    # One-to-one relationship with SliceObject class
    slice_object_id = Column(UUID, ForeignKey(
        camel2snake("SliceObject") + ".id"))
    slice_object = relationship(
        "SliceObject", back_populates="slice_constraints")


class Geographic(Base):
    """docstring for Geographic"""
    __tablename__ = camel2snake(__name__)
    # One-to-many relationship with Country enum
    country = relationship("Country")
    # One-to-one relationship with Geographic class
    slice_constraints_id = Column(UUID, ForeignKey(
        camel2snake("SliceConstraints") + ".id"))
    slice_constraints = relationship(
        "SliceConstraints", back_populates="geographic")


class Country(Base):
    """docstring for Country"""
    __tablename__ = camel2snake(__name__)
    # One-to-many relationship with Geographic class
    geographic_id = Column(UUID, ForeignKey(
        camel2snake("Geographic") + ".id"))
    geographic = relationship("Geographic", back_populates="country")


class SliceRequirements(Base):
    """docstring for SliceRequirements"""
    __tablename__ = camel2snake(__name__)
    # One-to-one relationship with SliceObject class
    slice_object_id = Column(UUID, ForeignKey(
        camel2snake("SliceObject") + ".id"))
    slice_object = relationship(
        "SliceObject", back_populates="slice_requirements")
    # One-to-many relationshipSliceTimeframe
    reliability = relationship("Reliability")


class Reliability(Base):
    """docstring for Reliability"""
    __tablename__ = camel2snake(__name__)
    # One-to-many relationship
    slice_requirements_id = Column(
        UUID, ForeignKey(camel2snake("SliceRequirements") + ".id"))
    slice_requirements = relationship(
        "SliceRequirements", back_populates="reliability")


class SliceLifecycle(Base):
    """docstring for SliceLifecycle"""
    __tablename__ = camel2snake(__name__)
    # One-to-one relationship with SliceObject class
    slice_object_id = Column(UUID, ForeignKey(
        camel2snake("SliceObject") + ".id"))
    slice_object = relationship(
        "SliceObject", back_populates="slice_lifecycle")


class SliceCost(Base):
    """docstring for SliceCost"""
    __tablename__ = camel2snake(__name__)
    # One-to-one relationship with CostModel class
    dc_model_id = Column(UUID, ForeignKey(
        camel2snake("CostModel") + ".id"))
    dc_model = relationship(
        "CostModel", foreign_keys=[dc_model_id])
    net_model_id = Column(UUID, ForeignKey(
        camel2snake("CostModel") + ".id"))
    net_model = relationship(
        "CostModel", foreign_keys=[net_model_id]
    )
    # One-to-one relationship with SliceObject class
    slice_object_id = Column(UUID, ForeignKey(
        camel2snake("SliceObject") + ".id"))
    slice_object = relationship(
        "SliceObject", back_populates="cost")


class CostModel(Base):
    """docstring for CostModel"""
    __tablename__ = camel2snake(__name__)
    value_euros = relationship("CostValue")


class CostValue(Base):
    """docstring for CostValue"""
    __tablename__ = camel2snake(__name__)
    lower_than_equal = Column(Integer)
    cost_model_id = Column(UUID, ForeignKey(
        camel2snake("CostModel") + ".id"))
    cost_model = relationship("CostModel", back_populates="value_euros")


class SliceTimeframe(Base):
    """docstring for SliceTimeframe"""
    __tablename__ = camel2snake(__name__)
    service_start_time_id = Column(
        UUID, ForeignKey(camel2snake("Timeframe") + ".id"))
    service_start_time = relationship(
        "Timeframe", foreign_keys=[service_start_time_id])
    service_stop_time_id = Column(
        UUID, ForeignKey(camel2snake("Timeframe") + ".id"))
    service_stop_time = relationship(
        "Timeframe", foreign_keys=[service_stop_time_id])
    # One-to-one relationship with SliceObject class
    slice_object_id = Column(UUID, ForeignKey(
        camel2snake("SliceObject") + ".id"))
    slice_object = relationship(
        "SliceObject", back_populates="slice_timeframe")


class ServiceDescription(Base):
    """docstring for ServiceDescription"""
    __tablename__ = camel2snake(__name__)
    # Many-to-one relationship with SliceObject class
    slice_object = relationship(
        "SliceObject", back_populates="service")
    # One-to-many for ServiceFunction class
    service_function_id = Column(UUID, ForeignKey(
        camel2snake("ServiceFunction") + ".id"))
    service_function = relationship("ServiceFunction")
    # One-to-many for ServiceLink class
    service_link_id = Column(UUID, ForeignKey(
        camel2snake("ServiceLink") + ".id"))
    service_link = relationship("ServiceLink")


class ServiceFunction(Base):
    """docstring for ServiceFunction"""
    __tablename__ = camel2snake(__name__)
    # Many-to-one relationship with SliceObject class
    service_description = relationship(
        "ServiceDescription", back_populates="service_function")
    service_element_type = Column(String)
    vdu = relationship(
        "VDU", back_populates="service_function")


class VDU(Base):
    """docstring for VDU"""
    __tablename__ = camel2snake(__name__)
    service_function_id = Column(UUID, ForeignKey(
        camel2snake("ServiceFunction") + ".id"))
    service_function = relationship("ServiceFunction", back_populates="vdu")
    # Many-to-one relationship with EPAAttributes class
    epa_attr_id = Column(UUID, ForeignKey(
        camel2snake("EPAAttributes") + ".id"))
    epa_attr = relationship("EPAAttributes")
    # Many-to-many relationship with VDUInterface class
    vdu_interface_id = Column(UUID, ForeignKey(
        camel2snake("VDUInterface") + '.id'))
    vdu_interface = relationship("VDUInterface", back_populates="vdu")


class EPAAttributes(Base):
    """docstring for EPAAttributes"""
    __tablename__ = camel2snake(__name__)
    host_epa_id = Column(UUID, ForeignKey(
        camel2snake("HostEPA") + ".id"))
    host_epa = relationship("HostEPA")
    hypervisor_epa = Column(UUID, ForeignKey(
        camel2snake("HypervisorEPA") + '.id'))
    hypervisor_epa = relationship("HypervisorEPA")
    vim_epa_id = Column(UUID, ForeignKey(camel2snake("VIMEPA") + '.id'))
    vim_epa = relationship("VIMEPA")
    vswitch_epa_id = Column(UUID, ForeignKey(
        camel2snake("VSwitchEPA") + '.id'))
    vswitch_epa = relationship("VSwitchEPA")


class HostEPA(Base):
    __tablename__ = camel2snake(__name__)
    epa_attributes = relationship("EPAAttributes", back_populates='host_epa')


class HypervisorEPA(Base):
    __tablename__ = camel2snake(__name__)
    epa_attributes = relationship("EPAAttributes", back_populates='host_epa')


class VIMEPA(Base):
    __tablename__ = camel2snake(__name__)
    epa_attributes = relationship("EPAAttributes", back_populates='host_epa')


class VSwitchEPA(Base):
    __tablename__ = camel2snake(__name__)
    epa_attributes = relationship("EPAAttributes", back_populates='host_epa')


class VDUInterface(Base):
    """docstring for VDUInterface"""
    __tablename__ = camel2snake(__name__)
    vdu = relationship("VDU", back_populates='vdu_interface')


class ServiceLink(Base):
    """docstring for ServiceLink"""
    __tablename__ = camel2snake(__name__)
    # Many-to-one relationship with SliceObject class
    service_description = relationship(
        "ServiceDescription", back_populates="service_link")
    service_element_type = Column(String)
    link = relationship("Link", back_populates="service_link")


class Link(Base):
    """docstring for Link"""
    __tablename__ = camel2snake(__name__)
    service_link_id = Column(UUID, ForeignKey(
        camel2snake("ServiceLink") + ".id"))
    service_link = relationship("ServiceLink", back_populates="link")


class SliceDescription(Base):
    """docstring for SliceDescription"""
    __tablename__ = camel2snake(__name__)
    # Many-to-one relationship with SliceObject class
    slice_object = relationship(
        "SliceObject", back_populates="slice")

然后运行python解释器:

>>> from model import SliceObject
>>> slice = SliceObject()

作为记录,没有发现任何类似的错误......所以如果你发现了一些,请帮助:)

【问题讨论】:

  • 请包含导致此错误的代码。
  • 我们需要一个最小的可重现示例;请使用代码围栏(代码前后各 3 个反引号)将代码粘贴到问题中。
  • 脚本的链接有问题。请将它们缩减为一个可重现的最小示例,并将代码放在问题本身中。
  • 将脚本粘贴到您的问题中是公认的方法。
  • 立即尝试...我已将代码放入问题正文中。

标签: python python-3.x sqlalchemy entity relationship


【解决方案1】:

问题出在__tablename__ 属性中使用__name____name__ 指的是模块的名称而不是类的名称。对于每个类,将其替换为具有所需名称的字符串(我想是类名)。

【讨论】:

    猜你喜欢
    • 2015-03-24
    • 2013-05-22
    • 2017-04-27
    • 2019-12-15
    • 1970-01-01
    • 2013-10-22
    • 2021-07-06
    • 2021-05-07
    • 2023-03-12
    相关资源
    最近更新 更多