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