sqlalchemy flush()를 입력하고 ID를 입력하시겠습니까?
저는 다음과 같은 일을 하고 싶습니다.
f = Foo(bar='x')
session.add(f)
session.flush()
# do additional queries using f.id before commit()
print f.id # should be not None
session.commit()
그렇지만f.id이라None제가 해보면요.어떻게 하면 이것을 작동시킬 수 있을까요?
저는 방금 같은 문제에 부딪혔고, 테스트 후에 이 답들 중 어느 것도 충분하지 않다는 것을 발견했습니다.
현재 또는 sqlalchemy.6+의 경우 매우 간단한 솔루션이 있습니다(이것이 이전 버전에 존재하는지는 모르겠지만 존재한다고 생각합니다).
session.message
코드는 다음과 같습니다.
f = Foo(bar=x)
session.add(f)
session.flush()
# At this point, the object f has been pushed to the DB,
# and has been automatically assigned a unique primary key id
f.id
# is None
session.refresh(f)
# refresh updates given object in the session with its state in the DB
# (and can also only refresh certain attributes - search for documentation)
f.id
# is the automatically assigned primary key ID given in the database.
그렇게 하는 거예요.
당신의 샘플 코드는 그대로 작동했어야 합니다.SQL 화학은 다음에 대한 가치를 제공해야 합니다.f.id기본 키 열을 자동 생성한다고 가정합니다. 키 은 기본 키속다같즉채다니집워시 됩니다.flush()생성된 대로 처리하고 호출하지 않습니다.commit()필요니다합. 은 다음중 .따라서 여기서 답은 다음 중 하나 이상에 있습니다.
- 매핑 세부 정보
- 사용 중인 백엔드에 이상한 특이점이 있는 경우(예: SQLite가 복합 기본 키에 대한 정수 값을 생성하지 않는 경우)
- 에코를 설정할 때 발생한 SQL이 하는 말입니다.
모두에게 감사합니다.열 매핑을 수정하여 문제를 해결했습니다.나를 위해.autoincrement=True필수 항목입니다.
원점:
id = Column('ID', Integer, primary_key=True, nullable=False)
수정 후:
id = Column('ID', Integer, primary_key=True, autoincrement=True, nullable=True)
그리고나서
session.flush()
print(f.id)
괜찮아요!
지난 몇 시간/일/어쨌든, 저는 위의 제안들을 실행에 옮기려고 노력했습니다.처음에는 모든 삽입 함수를 다음과 같이 작성했습니다.
_add = User(id, user_name, email, ...)
여기서 둥근 괄호 사이의 모든 항목은 없음, "usera", "a@example.com"에 대한 변수입니다.
다음은 내 사용자 테이블입니다.
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
user_name = Column(String(50), unique=True, nullable=False)
email = Column(String(100), unique=True, nullable=False)
SQLAlchemy는 자동 증분 ID로 레코드를 삽입하므로 _add 쿼리를 올바르게 처리합니다.또한 id 열에는 기본값이 설정되지 않습니다.
저는 위의 모든 옵션을 다양한 방법으로 시도했습니다(커밋 있음/없음, 플러시 있음/없음, 새로 고침 있음/없음, 문장 사이의 시간 초과 등).저는 심지어 전체 앱/데이터베이스 상호 작용을 몇 번 변경했습니다.그러나 모든 경우에 "_add.id"는 0을 반환하거나 "Instance"와 같은 것이 삭제되었거나 행이 존재하지 않습니다."
방금 저는 이렇게 생각했습니다. "지정된 테이블에 대한 열 이름도 정의하여 _add 쿼리를 조금 다르게 써야 할 것 같습니다."
_add = User(id=None, user_name=user_name, email=email, etc)
강조하려면 _add 쿼리에서 id=, user_name=, email=를 기록합니다.이제 이 순서대로 다음 문을 지정하면 SQLAlchemy는 삽입된 ID를 반환합니다!
session.add(_add)
print(_add.id) <-- returns None
session.flush() <-- does **not** insert record into database, but does increment id,
waiting to be committed. Flush may be omitted, because
session.commit() unconditionally issues session.flush()*
print(_add.id) <-- returns incremented id
session.commit() <-- commit is needed to actually insert record into database
print(_add.id) <-- returns incremented id
비록 답이 제공되었지만, _add 쿼리에서 누락된 열 이름과 따라서 나의 게으름이 나의 문제의 원인인지는 명확하지 않았습니다.이것이 누군가가 동일한 문제 해결을 피하는 데 도움이 되기를 바랍니다.
dpb가 제공한 답변과 달리, 새로 고침은 필요하지 않습니다.플러시하면 id 필드에 액세스할 수 있습니다. sqlalchemy는 백엔드에서 자동으로 생성되는 id를 자동으로 새로 고칩니다.
저는 이 문제에 부딪혔고 정확한 이유를 조사한 결과, 제 모델은 id를 정수 필드로 만들고 id는 숨겨진 필드로 표현했습니다(제가 제 폼에 id를 표시하고 싶지 않았기 때문입니다).숨겨진 필드는 기본적으로 텍스트로 표시됩니다.widget=hiddenInput()으로 양식을 정수 필드로 변경하면 문제가 해결되었습니다.
핵심 솔루션은 다른 훨씬 오래된 답변에서도 언급되었지만, 이는 최신 비동기 API를 사용합니다.
sqlalchemy==1.4(2.0 스타일)를 사용하면 다음과 같이 작동합니다.
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
echo=False,
)
# expire_on_commit=False will prevent attributes from being expired
# after commit.
async_session = sessionmaker(
engine, expire_on_commit=False, class_=AsyncSession,
)
# default kwarg autoflush=True
async with async_session() as session:
async with session.begin():
f = Foo(bar='x')
session.add(f)
print(f.id)
# None
await session.flush()
print(f.id)
# not None
# commits transaction, closes session
나는 한때 할당된 것에 대해 문제가 있었습니다.0전화하기 전에 미리 알려주세요.session.add방법.ID가 데이터베이스에 의해 올바르게 할당되었지만 세션에서 올바른 ID가 검색되지 않았습니다.session.flush().
내 코드는 다음과 같이 작동합니다.
f = Foo(bar="blabla")
session.add(f)
session.flush()
session.refresh(f, attribute_names=[columns name that you want retrieve]
# so now you can access the id inserted, for example
return f.id # id inserted will be returned
사용해 보십시오.session.save_or_update(f)대신에session.add(f).
언급URL : https://stackoverflow.com/questions/1316952/sqlalchemy-flush-and-get-inserted-id
'programing' 카테고리의 다른 글
| VueNuxtNextServerInit에서 데이터를 로드하지 않습니다. (0) | 2023.06.13 |
|---|---|
| sql에서 열 아래의 열 합계 가져오기 (0) | 2023.06.13 |
| Oracle에서 고유 인덱스를 생성하면서 null을 무시하려면 어떻게 해야 합니까? (0) | 2023.06.13 |
| 문자열 배열의 값 일치 (0) | 2023.06.13 |
| 목표 C(iPhone)의 Excel 파일에서 데이터 읽기 (0) | 2023.06.13 |