[英]How to prevent UUID primary key for new SQLAlchemy objects being created with the same value
我有一個 for 循環,它創建一個新的“行”對象,在將對象提交到 Postgres 數據庫中的表之前用數據填充屬性。 我要插入的表(以及對象)采用 UUID 的主鍵,只有在第一次提交后所有新創建的行對象中的循環的第一次迭代后,這個值保持不變。
我對解決方案有點迷茫,但是我認為這可能與我處理數據庫會話的方式有關。 在寫這篇文章時,我還注意到我在invite_users
和invite_user
函數中使用了相同的變量名( new_user
)。 雖然 Python 會認為它們在不同的范圍內(我認為),但我想知道 SQLALchemy 會話是否會?
請注意,我已經刪除了很多我認為在問題的上下文中是多余的代碼 - 主要是更多的列等。此外, invite_user
函數在其他地方使用,因此invite_users
僅用於批量“邀請”。
這是一個片段,顯示了表類定義和Column
定義的開始:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects import postgresql
import uuid
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(postgresql.UUID(as_uuid=True), default=uuid.uuid4(), primary_key=True)
email = Column(String, unique=True)
這是我用來創建和銷毀會話的函數:
from contextlib import contextmanager
from sqlalchemy import create_engine
@contextmanager
def db_session(db_url):
engine = create_engine(db_url, convert_unicode=True)
connection = engine.connect()
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=engine))
yield db_session
db_session.close()
connection.close()
下面是遍歷 JSON 對象數組的函數的一部分:
def invite_users(json_dict):
exceptions = {}
with db_session(environ['CONNECTION_STRING']) as session:
for new_user in json_dict['users']:
try:
invite_user(
session,
info['email_address']
)
# I'm catching exceptions and storing them to handle them later
except Exception as e:
exceptions[user_info['email_address']] = e
pass
這是將行添加到會話並嘗試提交它的invite_user
函數:
from project.database import * # this contains the User table class above
from project.exceptions import *
def invite_user(session, email):
new_user = User(
email=email
)
session.add(new_user)
try:
session.commit()
except exc.IntegrityError as e:
session.rollback()
raise DuplicateViolation(f"User already invited") from None
所以我遍歷字典中的電子郵件地址( json_dict['emails']
)。 然后,我將每封電子郵件連同當前的數據庫session
一起傳遞給用戶。 我這樣做是為了避免為每個invite_user
調用創建一個會話,因為從性能角度來看,這似乎比在invite_user
函數中創建一個新session
更明智,因為這將導致許多會話被創建和銷毀。
我認為我的Column
定義足以處理每次提交User
行對象時新 UUID 的生成。 但是,如果我向invite_users
函數傳遞多個電子郵件地址,第一個用戶會被添加一個新的UUID,第二個用戶會被分配相同的UUID。 如果我通過它一個電子郵件地址一切都很好。
我不想依賴查詢數據庫中的現有行。 我完全依靠數據庫約束來防止重復,異常處理用於向用戶報告錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.