简体   繁体   中英

Using a different schema for the same declarative Base in sqlalchemy

I am new to both Pyramid and SQLAlchemy. I am working on a Python Pyramid project with SQLAlchemy. I have a simple model set up below. How would I go about being able to use this with different schemas at run-time? This will be a PostgreSQL database backend. Right now, "public" is hard-coded into the declarative base model. I would need the ability to use this same model with different schema. What is the best approach? Unless I missed it, the documentation at SQLAlchemy seemed unclear to me.

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, BigInteger

    __all__ = [
        "LoadTender"
    ]
    __all__.sort()

    Base = declarative_base()


    class LoadTender(Base):
        __tablename__ = "load_tenders"
        __table_args__ = {"schema": "public"}

        id = Column("pkey", BigInteger, primary_key=True)

        def __repr__(self):
            return "" % self.id

EDIT: I have appeared to solve my issue, I am updating the snippet to show what I did below.

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, BigInteger

__all__ = [
    "LoadTender"
]
__all__.sort()

Base = declarative_base()

class ClientMixin(object):
    __table_args__ = {"schema": "client_schema_name"}


class LoadTenderMixin(object):
    __tablename__ = "load_tenders"

    id = Column("pkey", BigInteger, primary_key=True)

    def __repr__(self):
        return "" % self.id


class ClientLoadTender(LoadTenderMixin, ClientMixin, Base):
    pass

I think you need a different model for each schema. __abstract__ can make this less painful. This follows on to Paul Yin's answer...

  1. Define an __abstract__ LoadTender model, so you don't have to keep coding it.

     #base.py class LoadTender(Base): __abstract__ = True id = ... def __repr__ ... 
  2. Put a schema-specific Base in the hierarchy for each schema.

     #schema1.py from base import LoadTender PublicBase = declarative_base(metadata=MetaData(schema='public')) class LoadTender(PublicBase, LoadTender): __tablename__ = 'load_tenders' 
  3. Do the same for other schema.

just a guess

LoadTender.__table_args__["schema"] = "whatever"

Probably best to put it somewhere where your app configurator is creating the app

You can have a base module in package model

app\
    models\
        base.py
        schema1.py
        schema2.py
    views\
    ...

declare Base in base.py, then import it to other schemas

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