Как исправить `InvalidRequestError: не может прикрепить экземпляр <ClassName AT 0x7Baada2f3cb0>` В отношениях SQLALCHEMYPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как исправить `InvalidRequestError: не может прикрепить экземпляр <ClassName AT 0x7Baada2f3cb0>` В отношениях SQLALCHEMY

Сообщение Anonymous »

Я уже прошел через несколько ответов на SO (например, этот и этот, но ни один из них, кажется, не работает для меня. />

Код: Выделить всё

import sqlalchemy as sqal

client_group_association = sqal.Table(
"client_group_association",
Base.metadata,
sqal.Column("client_id", sqal.UUID, sqal.ForeignKey("client_info.id"), primary_key=True),
sqal.Column("group_id", sqal.UUID, sqal.ForeignKey("group_info.id"), primary_key=True)
)

class ClientInfo(Base):
"""Stores information of clients."""

__tablename__ = "client_info"

id: Mapped[uuid6.UUID] = mapped_column(sqal.UUID(as_uuid=True), primary_key=True,
insert_default=uuid6.uuid7())

name: Mapped[str] = mapped_column(sqal.String, nullable=False)
email: Mapped[str] = mapped_column(sqal.String, nullable=False)
phone: Mapped[str] = mapped_column(sqal.String, nullable=False)
age: Mapped[int] = mapped_column(sqal.Integer, nullable=False)

# Other unrelated fields

groups: Mapped[List[uuid6.UUID]] = mapped_column(UUIDList, nullable=True)

group_objs: Mapped[List["GroupInfo"]] = relationship(
secondary=client_group_association,
back_populates="client_objs"
)

__table_args__ = (sqal.UniqueConstraint('name', 'email', 'phone', name='_unique_client_details'),
sqal.ForeignKeyConstraint(['groups'], ['group_info.id'],
onupdate='CASCADE', ondelete='CASCADE'))

class GroupInfo(Base):
"""Stores information of groups."""

__tablename__ = "group_info"

id: Mapped[uuid6.UUID] = mapped_column(sqal.UUID(as_uuid=True), primary_key=True,
insert_default=uuid6.uuid7())
location: Mapped[Locations] = mapped_column(sqal.Enum(Locations), nullable=False)

members: Mapped[List[uuid6.UUID]] = mapped_column(UUIDList, nullable=True)

client_objs: Mapped[List["ClientInfo"]] = relationship(
secondary=client_group_association,
back_populates="group_objs"
)

__table_args__ = (sqal.UniqueConstraint('members', name='_unique_members'),
sqal.ForeignKeyConstraint(['members'], ['client_info.id'],
onupdate='CASCADE', ondelete='CASCADE'))
Моя цель состояла в том, чтобы установить правильную двунаправленную связь между множеством-кожу, так что я могу получить доступ к объектам GroupInfo непосредственно из объекта ClientInfo (который представляет группы, в которых находится пользователь) и ClientInfo из Groupinfo (представляющий клиенты в группе). Asyncsession , который я получаю следующим образом:

Код: Выделить всё

__LOCK: asyncio.Lock = asyncio.Lock()
__SQL_ENGINE: AsyncEngine = create_async_engine(f"sqlite+aiosqlite:///{DATABASE_NAME}")

@contextlib.asynccontextmanager
async def get_async_session(self, locked: bool = True) -> AsyncIterator[AsyncSession]:

Session = sessionmaker(bind=self.__SQL_ENGINE, class_=AsyncSession)

if locked:
async with self.__LOCK:
async with Session() as session:
yield session
else:
async with Session() as session:
yield session
< /code>
, казалось, сработало некоторое время; Я мог бы получить вложенные объекты, используя вложенные операторы SelectInload 
:

Код: Выделить всё

stmt = select(ClientInfo).where(...)\
.limit(10)\
.options(selectinload(ClientInfo.group_objs)\
.selectinload(GroupInfo.client_objs))  # Force eager-loading
< /code>
Каждый раз, когда я хочу создать новую группу, теперь я сталкиваюсь с < /p>
sqlalchemy.exc.InvalidRequestError: Can't attach instance ; another instance with key (, (UUID('019634d4-1422-7a0e-9a21-96941acc10dd'),), None) is already present in this session.
error.
Обратите внимание, что каждый раз, когда я хочу получить доступ к базе данных, я создаю новый сеанс. Это самая важная часть транзакции, потому что я ссылаюсь на объекты клиента через эти отношения в будущем.

Код: Выделить всё

group_info: GroupInfo = GroupInfo(id=uuid6.uuid7(),
location=self.location,
members=list(self.clients.keys()))

for client_info in self.clients.values():
group_info.client_objs.append(client_info)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
, скорее всего, это происходит потому, что я загружаю некоторые объекты ClientInfo , чтобы пользователь выбирал человека, что гарантирует, что все объекты ClientInfo , которые я хочу добавить к отношениям, уже в сеансе. Но что меня удивляет, что эта выбравшаяся часть сделана в отдельном сеансе в отдельном классе.

Код: Выделить всё

session.expunge(client_info)
session.expire(client_info)
Я также создал две переменные экземпляра в основном классе, которые будут удерживать отношения clientInfo.group_objs Field и GroupInfo.client_objs и попробуйте использовать это, если добавление в сеанс возвращает ошибку:
# In constructor
self.group_objs_relationship = None
self.client_objs_relationship = None

# Later in the separate class
bot.client_object_relationship = group_info.client_objs # Nullability checked
bot.group_objs_relationship = group_info.client_objs[0].group_objs # Nullability checked

# When adding the new group:
try:
session.add(group_info)

except sqal.exc.InvalidRequestError:

print('Error raised when adding GroupInfo, trying alternate path!')

if bot.group_objs_relationship:
bot.group_objs_relationship.append(group_info)
else:
print('Sorry, could not add that.')

finally:
await session.commit()

Это работает для GroupInfo , но я понятия не имею, как добавить эти объекты ClientInfo в объект GroupInfo перед совершением, потому что удаление не работает в этом случае.
.>

Подробнее здесь: https://stackoverflow.com/questions/795 ... x7baada2f3
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»