Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alembic Migrations on Multiple Models

I am attempting to create a revision with --autogenerate using Alembic for two Models, but am receiving a duplicate table keys error. Does, a schema need to be specified? If so, how can it be set? The documentation I've read says to use __table_args__ = {'schema': 'somename'}, but that hasn't helped. Any tips or suggestions are greatly appreciated.

My current setup is:

base.py

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

workspace.py

from sqlalchemy import Column, Integer, String
from base import Base

class WorkspaceModel(Base):

    __tablename__ = 'workspaces'

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

host.py

from sqlalchemy import Column, Integer, String
from base import Base

class HostModel(Base):

    __tablename__ = 'hosts'

    id = Column(Integer, primary_key=true)
    ip = Column(String)

alembic/env.py

from host import HostModel
from workspace import WorkspaceModel
target_metadata = [HostModel.metadata, WorkspaceModel.metadata]

Error

ValueError: Duplicate table keys across multiple MetaData objects: "hosts", "workspaces"
like image 203
chirinosky Avatar asked Jan 01 '18 22:01

chirinosky


2 Answers

To make it clear from what @esdotzed and @univerio said, you have to use a single Base.metadata - but still import the individual models.

In the original question, this is how the alembic/env.py should look like:

from base import Base

# This two won't be referenced, but *have* to be imported to populate `Base.metadata`
from host import HostModel
from workspace import WorkspaceModel

target_metadata = Base.metadata

If you didn't import both models, the autogenerated migration would end up deleting your whole database - because Base.metadata doesn't know about any model by itself.

like image 136
mgarciaisaia Avatar answered Oct 11 '22 16:10

mgarciaisaia


quoting univerio's answer from the comment section:

target_metadata should just be target_metadata = Base.metadata

Using Base.metadata doesn't mean you can remove the imports from host import HostModel and from workspace import WorkspaceModel

It worked for me.

like image 23
esdotzed Avatar answered Oct 11 '22 17:10

esdotzed