简体   繁体   中英

SQLAlchemy has maximum number of relationships?

I'm using python 3.6 and SQLAlchemy 1.3.8 and I'm facing an issue a little stranger...I'm receiving the same exception for multiple relationships (24 classes that relates to each other by many types of relationship) and the same issue happen exactly the same but with differ tables each time I run the script. I wasn't facing it when the number of classes was less then twenty...so, is it possible that there's a maximum number of relationships?

The traceback is:

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'

To reproduce, use the scripts bellow

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")

And run the python interpreter then the following:

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

For the record, didn't found any similar error...so if you found some, please help :)

The problem was in the use of __name__ in __tablename__ attribute. __name__ refers to the name of the module not the name of the class. For each class, substitute it for a string with the desired name (which I suppose is the class name).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM