简体   繁体   English

SQLAlchemy具有最大数量的关系?

[英]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. 我正在使用python 3.6和SQLAlchemy 1.3.8,并且遇到了一个有点陌生的问题...我在多个关系(24个通过多种关系类型相互关联的类)中收到相同的异常每次运行脚本时,相同的问题完全相同,但表不同。 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 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: 并运行python解释器,然后执行以下操作:

>>> 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____tablename__属性中使用__tablename__ __name__ refers to the name of the module not the name of the class. __name__是指模块的名称,而不是类的名称。 For each class, substitute it for a string with the desired name (which I suppose is the class name). 对于每个类,将其替换为具有所需名称(我想是类名称)的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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