Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在SQLAlchemy中动态设置切分的_tablename __uu?_Python_Mysql_Orm_Sqlalchemy - Fatal编程技术网

Python 在SQLAlchemy中动态设置切分的_tablename __uu?

Python 在SQLAlchemy中动态设置切分的_tablename __uu?,python,mysql,orm,sqlalchemy,Python,Mysql,Orm,Sqlalchemy,为了处理不断增长的数据库表,我们对表名进行切分。因此,我们可以将数据库表命名为: table_md5one table_md5two table_md5three from sqlalchemy import MetaData, Table, Column def get_table_object(self, md5hash): metadata = MetaData() table_name = 'table_' + md5hash table_object = T

为了处理不断增长的数据库表,我们对表名进行切分。因此,我们可以将数据库表命名为:

table_md5one
table_md5two
table_md5three
from sqlalchemy import MetaData, Table, Column

def get_table_object(self, md5hash):
    metadata = MetaData()
    table_name = 'table_' + md5hash
    table_object = Table(table_name, metadata,
        Column('Column1', DATE, nullable=False),
        Column('Column2', DATE, nullable=False)
    )
    clear_mappers()
    mapper(ActualTableObject, table_object)
    return ActualTableObject
所有表都具有完全相同的模式

我们如何使用SQLAlchemy并为与之对应的类动态指定表名?看起来声明性的_base()类需要预先指定tablename


最终会有太多的表,无法从父/基类手动指定派生类。我们希望能够构建一个能够动态设置表名的类(可能作为参数传递给函数)。

好的,我们使用了自定义SQLAlchemy声明,而不是声明性声明

因此,我们创建一个动态表对象,如下所示:

table_md5one
table_md5two
table_md5three
from sqlalchemy import MetaData, Table, Column

def get_table_object(self, md5hash):
    metadata = MetaData()
    table_name = 'table_' + md5hash
    table_object = Table(table_name, metadata,
        Column('Column1', DATE, nullable=False),
        Column('Column2', DATE, nullable=False)
    )
    clear_mappers()
    mapper(ActualTableObject, table_object)
    return ActualTableObject
其中ActualTableObject是映射到表的类。

在中,您可以找到一种使用自定义
类的方法,例如,该类可以动态计算
\uuuu tablename\uuuu
属性:

class Base(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
这里唯一的问题是我不知道你的散列从哪里来,但这应该是一个很好的起点

如果不是所有的表都需要这种算法,而只是一个表需要这种算法,您可以在您感兴趣的表上使用
声明的\u attr

试试这个

import zlib

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, BigInteger, DateTime, String

from datetime import datetime

BASE = declarative_base()
ENTITY_CLASS_DICT = {}


class AbsShardingClass(BASE):

    __abstract__ = True

def get_class_name_and_table_name(hashid):
    return 'ShardingClass%s' % hashid, 'sharding_class_%s' % hashid

def get_sharding_entity_class(hashid):
    """
    @param hashid: hashid
    @type hashid: int
    @rtype AbsClientUserAuth
    """

    if hashid not in ENTITY_CLASS_DICT:
        class_name, table_name = get_class_name_and_table_name(hashid)
        cls = type(class_name, (AbsShardingClass,),
                   {'__tablename__': table_name})
        ENTITY_CLASS_DICT[hashid] = cls

    return ENTITY_CLASS_DICT[hashid]

cls = get_sharding_entity_class(1)
print session.query(cls).get(100)

您可以使用tablename参数编写一个函数,并通过设置适当的属性将类发回

def get_class(table_name):

   class GenericTable(Base):

       __tablename__ = table_name

       ID= Column(types.Integer, primary_key=True)
       def funcation(self):
        ......
   return GenericTable
然后,您可以使用以下方法创建表:

get_class("test").__table__.create(bind=engine)  # See sqlachemy.engine

由于我坚持使用声明性类,并通过给定参数动态指定它们的
\uuuuu tablename\uuuuu
,在其他解决方案失败数天和研究SQLAlchemy内部结构数小时后,我提出了以下解决方案,我认为它简单、优雅且无竞争条件

def get_model(suffix):
    DynamicBase = declarative_base(class_registry=dict())

    class MyModel(DynamicBase):
        __tablename__ = 'table_{suffix}'.format(suffix=suffix)

        id = Column(Integer, primary_key=True)
        name = Column(String)
        ...

    return MyModel
因为他们有自己的
class_注册表
,所以您不会看到这样的警告:

此声明性基已包含与mypackage.models.MyModel具有相同类名和模块名的类,并将在字符串查找表中被替换

因此,您将无法通过字符串查找从其他模型中引用它们。但是,将这些即时声明的模型也用于外键,效果非常好:

ParentModel1 = get_model(123)
ParentModel2 = get_model(456)

class MyChildModel(BaseModel):
    __tablename__ = 'table_child'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    parent_1_id = Column(Integer, ForeignKey(ParentModel1.id))
    parent_2_id = Column(Integer, ForeignKey(ParentModel2.id))
    parent_1 = relationship(ParentModel1)
    parent_2 = relationship(ParentModel2)

如果您只使用它们来查询/插入/更新/删除,而没有留下任何引用,例如来自另一个表的外键引用,那么它们、它们的基类以及它们的class_注册表将被垃圾收集,因此不会留下任何跟踪。

而不是使用命令式创建表对象,您可以使用常用的声明性_base并使用闭包来设置表名,如下所示:

def make_class(Base, table_name):
    class User(Base):
        __tablename__ = table_name
        id = Column(Integer, primary_key=True)
        name= Column(String)

    return User

Base = declarative_base()
engine = make_engine()
custom_named_usertable = make_class(Base, 'custom_name')
Base.metadata.create_all(engine)

session = make_session(engine)
new_user = custom_named_usertable(name='Adam')
session.add(new_user)
session.commit()
session.close()
engine.dispose()

这就是我过去所做的,我也希望看到一个不同的解决方案。@jkmac@Suman我添加了一个带有自定义
Base
类的解决方案,这可能会有所帮助,具体取决于用例。@jkmac试试我的解决方案。有没有用于切分表的内置解决方案?来自文档:“clear\u mappers()不是用于正常使用,因为在非常特定的测试场景之外,它实际上没有有效的用法。“如果您试图在模型定义而不是声明性基类上执行此操作,则它是不正确的,并抛出
InvalidRequestError
。添加了一个编辑,但只是为了防止编辑不被接受,用于扩充基础的更新URL不再有效。这一节现在可以在这里找到:在我看来,这是解决这个问题的最有效的方法。