sqlalchemy 尝试两次创建我的表

sqlalchemy tries to create my tables twice

sqlalchemy 搜索我的表两次。

找了一整天的问题,没找到

apps/books/models


print('before')


class Book(Base):
    __tablename__ = 'books'
    id = Column(Integer, primary_key=True)

    title = Column(String, nullable=False,unique=True)
    descriptions = Column(String)
    file_path = Column(String,unique=True)

    users = relationship("User", secondary="book_users", back_populates='books')

book_users = Table('book_users', Base.metadata,
    Column('book_id', ForeignKey('books.id'), primary_key=True),
    Column('users_id', ForeignKey('users.id'), primary_key=True),
)
print('after')

class Part(Base):
    __tablename__ = 'parts'
    id = Column(Integer, primary_key=True)

    title = Column(String, nullable=False)
    descriptions = Column(String)
    
    book_id = Column('book_id',ForeignKey('books.id'))
    book = relationship('Book',backref='parts')

apps/users/models


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True)
    last_name = Column(String)
    hashed_password = Column(String)

    books = relationship("Book", secondary="book_users", back_populates='users')

apps/database


from decouple import config

USER = config('user')
PASSWORD = config('password')
DB = config('db')
HOST = config('host')


SQLALCHEMY_DATABASE_URL = f"postgresql://{USER}:{PASSWORD}@{HOST}/{DB}"


engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


Base = declarative_base()

def get_db():
    db = Session(bind=engine)
    try:
        yield db
    finally:
        db.close()

我试过不解耦,没用

apps/main

import sys,os
sys.path.insert(0, os.path.abspath(".."))
sys.path.insert(0, os.path.abspath("..."))

from fastapi import FastAPI
from database import engine, Base

from users.routers import router as router_user
from books.routers import router as router_book

def create_db():
    Base.metadata.create_all(bind=engine)

app = FastAPI(title="Shop")

@app.on_event("startup")
def on_startup():
    create_db()

app.include_router(router=router_user)
app.include_router(router=router_book)


插入只是我导入的一种方式)

异常

before
after
before
Process SpawnProcess-4:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/multiprocessing/process.py", line 315, in _bootstrap
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/uvicorn/subprocess.py", line 76, in subprocess_started
    target(sockets=sockets)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/uvicorn/server.py", line 60, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "uvloop/loop.pyx", line 1501, in uvloop.loop.Loop.run_until_complete
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/uvicorn/server.py", line 67, in serve
    config.load()
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/uvicorn/config.py", line 458, in load
    self.loaded_app = import_from_string(self.app)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/uvicorn/importer.py", line 21, in import_from_string
    module = importlib.import_module(module_str)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/kana/Desktop/author/apps/./main.py", line 9, in <module>
    from books.routers import router as router_book
  File "/Users/kana/Desktop/author/apps/./books/routers.py", line 13, in <module>
    from .models import Book, Part
  File "/Users/kana/Desktop/author/apps/./books/models.py", line 9, in <module>
    class Book(Base):
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/orm/decl_api.py", line 72, in __init__
    _as_declarative(reg, cls, dict_)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/orm/decl_base.py", line 126, in _as_declarative
    return _MapperConfig.setup_mapping(registry, cls, dict_, None, {})
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/orm/decl_base.py", line 177, in setup_mapping
    return cfg_cls(registry, cls_, dict_, table, mapper_kw)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/orm/decl_base.py", line 322, in __init__
    self._setup_table(table)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/orm/decl_base.py", line 811, in _setup_table
    table_cls(
  File "<string>", line 2, in __new__
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/util/deprecations.py", line 309, in warned
    return fn(*args, **kwargs)
  File "/Users/kana/Desktop/author/env/lib/python3.10/site-packages/sqlalchemy/sql/schema.py", line 584, in __new__
    raise exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: Table 'books' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

你怎么看,我的程序在 apps/books/models

之后坏掉了

class 书籍(基础)

如果我切换 Book 和 Part,错误将在 Part

任何提示将不胜感激

如果您遇到这个问题,您需要彻底更改程序中的每个导入,从根目录中指定相同的路径。

问题的另一个原因可能是项目的架构。

我的数据库没有创建表的第一个原因是因为它与表处于同一级别。在我的例子中,当桌子在 apps/books/models 时,它在 apps/utils/main 级别,他将其添加到 Base.metadata.tables,但是当他移动到 apps/utils/main 时,Base.metadata.tables 列表是空的。 当我把它拉到现在的水平时,问题就消失了

简历:

string Base.metadata.create_all(bind=engine) 必须比模块 models (或您的模型的另一个名称)高一个级别)

并更新您的导入