Skip to content

Commit cc6bfbf

Browse files
committed
fixed sqla orm delete_object
1 parent 08d1f7f commit cc6bfbf

File tree

4 files changed

+79
-2
lines changed

4 files changed

+79
-2
lines changed

fastapi_jsonapi/data_layers/sqla_orm.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,10 @@ async def delete_object(self, obj: TypeModel, view_kwargs: dict):
386386
:param view_kwargs: kwargs from the resource view.
387387
"""
388388
await self.before_delete_object(obj, view_kwargs)
389+
stmt = delete(self.model).where(self.model.id == obj.id)
390+
389391
try:
390-
await self.session.delete(obj)
392+
await self.session.execute(stmt)
391393
await self.save()
392394
except DBAPIError as e:
393395
await self.session.rollback()

tests/models.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from sqlalchemy import JSON, Column, DateTime, ForeignKey, Index, Integer, String, Text
55
from sqlalchemy.ext.declarative import declarative_base
6-
from sqlalchemy.orm import declared_attr, relationship
6+
from sqlalchemy.orm import backref, declared_attr, relationship
77
from sqlalchemy.types import CHAR, TypeDecorator
88

99
from tests.common import is_postgres_tests, sqla_uri
@@ -390,3 +390,25 @@ class Delta(Base):
390390
name = Column(String)
391391
gammas: List["Gamma"] = relationship("Gamma", back_populates="delta", lazy="noload")
392392
betas: List["Beta"] = relationship("Beta", secondary="beta_delta_binding", back_populates="deltas", lazy="noload")
393+
394+
395+
class CascadeCase(Base):
396+
__tablename__ = "cascade_case"
397+
398+
id = Column(Integer, primary_key=True, autoincrement=True)
399+
parent_item_id = Column(
400+
Integer,
401+
ForeignKey(
402+
"cascade_case.id",
403+
onupdate="CASCADE",
404+
ondelete="CASCADE",
405+
),
406+
nullable=True,
407+
)
408+
sub_items = relationship(
409+
"CascadeCase",
410+
backref=backref("parent_item", remote_side=[id]),
411+
)
412+
413+
if TYPE_CHECKING:
414+
parent_item: Optional["CascadeCase"]

tests/schemas.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,21 @@ class SelfRelationshipSchema(BaseModel):
409409
)
410410

411411

412+
class CascadeCaseSchema(BaseModel):
413+
name: str
414+
parent_item: Optional["CascadeCaseSchema"] = Field(
415+
relationship=RelationshipInfo(
416+
resource_type="cascade_case",
417+
),
418+
)
419+
sub_items: Optional[list["CascadeCaseSchema"]] = Field(
420+
relationship=RelationshipInfo(
421+
resource_type="cascade_case",
422+
many=True,
423+
),
424+
)
425+
426+
412427
class CustomUserAttributesSchema(UserBaseSchema):
413428
spam: str
414429
eggs: str

tests/test_api/test_api_sqla_with_includes.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from tests.models import (
3232
Alpha,
3333
Beta,
34+
CascadeCase,
3435
Computer,
3536
ContainsTimestamp,
3637
CustomUUIDItem,
@@ -1474,6 +1475,43 @@ async def test_create_with_relationship_to_the_same_table(self):
14741475
"meta": None,
14751476
}
14761477

1478+
async def test_cascade_delete(self, async_session: AsyncSession):
1479+
resource_type = "cascade_case"
1480+
app = build_app_custom(
1481+
model=CascadeCase,
1482+
schema=SelfRelationshipSchema,
1483+
resource_type=resource_type,
1484+
)
1485+
1486+
top_item = CascadeCase()
1487+
sub_item_1 = CascadeCase(parent_item=top_item)
1488+
sub_item_2 = CascadeCase(parent_item=top_item)
1489+
async_session.add_all(
1490+
[
1491+
top_item,
1492+
sub_item_1,
1493+
sub_item_2,
1494+
],
1495+
)
1496+
await async_session.commit()
1497+
1498+
assert sub_item_1.parent_item_id == top_item.id
1499+
assert sub_item_2.parent_item_id == top_item.id
1500+
1501+
async with AsyncClient(app=app, base_url="http://test") as client:
1502+
url = app.url_path_for(f"delete_{resource_type}_detail", obj_id=top_item.id)
1503+
1504+
res = await client.delete(url)
1505+
assert res.status_code == status.HTTP_204_NO_CONTENT, res.text
1506+
1507+
top_item_stmt = select(CascadeCase).where(CascadeCase.id == top_item.id)
1508+
top_item = (await async_session.execute(top_item_stmt)).one_or_none()
1509+
assert top_item is None
1510+
1511+
sub_items_stmt = select(CascadeCase).where(CascadeCase.id.in_([sub_item_1.id, sub_item_2.id]))
1512+
sub_items = (await async_session.execute(sub_items_stmt)).all()
1513+
assert sub_items == []
1514+
14771515
async def test_create_with_timestamp_and_fetch(self, async_session: AsyncSession):
14781516
resource_type = "contains_timestamp_model"
14791517

0 commit comments

Comments
 (0)