Skip to content

Commit

Permalink
Implemented delete_filter, allowing conditions / column filters to de…
Browse files Browse the repository at this point in the history
…lete (#68)

* implemented delete_filter, allowing conditions / column filters to delete in 1 query

* cleaned up local deep_join variable references

* updated deletion check to count instead of integer response of delete_filter - not supported by pg

---------

Co-authored-by: Joshua (codemation) <[email protected]>
  • Loading branch information
codemation and Joshua (codemation) authored Sep 28, 2023
1 parent 8fee22e commit 5b54d6e
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,22 @@ See also filtering [operators](https://pydbantic.readthedocs.io/en/latest/model-

### Deleting
```python
# remove all managers not employed anymore
# one by one
for manager in await Employee.filter(
position=hr_manager,
is_employed=False
):
await manager.delete()
```

```python
# all at once
await Employee.delete_filter(
Employee.is_employed == True
)

```

### Updating
```python
# raise salary of all managers
Expand Down
5 changes: 5 additions & 0 deletions docs/model-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ terminated_employees = await Employees.filter(
await Employees.delete_many(terminated_employees)
```

```python
await Employees.delete_filter(
Employees.contains('name', 'terminated')
)
```

### Models with arrays of Foreign Objects

Expand Down
26 changes: 17 additions & 9 deletions pydbantic/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1267,7 +1267,6 @@ async def exists(cls, **column_values: dict) -> bool:
def deep_join(
cls: Type[T],
model_ref,
model_ref_primary_key: str,
column_ref: str,
session_query: Query,
tables_to_select: list,
Expand Down Expand Up @@ -1312,12 +1311,7 @@ def deep_join(

for foreign_model, column_ref in foreign_models:
session_query, tables_to_select = foreign_model.deep_join(
cls,
primary_key,
column_ref,
session_query,
tables_to_select,
models_selected,
cls, column_ref, session_query, tables_to_select, models_selected
)
return session_query, tables_to_select

Expand Down Expand Up @@ -1363,7 +1357,6 @@ async def select(
][1]
sel, tables_to_select = foreign_model.deep_join(
cls,
primary_key,
column_name,
sel,
tables_to_select,
Expand Down Expand Up @@ -1654,7 +1647,6 @@ async def filter(
continue
sel, tables_to_select = foreign_model.deep_join(
cls,
primary_key,
column_name,
sel,
tables_to_select,
Expand Down Expand Up @@ -1923,6 +1915,22 @@ async def delete_many(cls: Type[T], rows: List[T]) -> int:
query, _ = cls.where(delete(table), {}, delete_condition)
return await database.execute(query, None)

@classmethod
async def delete_filter(
cls: Type[T], *conditions: List[DataBaseModelCondition], **column_filters
) -> Optional[int]:
table = cls.get_table()
database = cls.__metadata__.database

columns = [k for k in cls.__fields__]
if not column_filters and not conditions:
raise Exception(
f"{cls.__name__}.delete_filter() expects keyword arguments for columns: {columns} or conditions"
)

query, values = cls.where(delete(table), column_filters, *conditions)
return await database.execute(query, None)

async def delete(self) -> int:
"""
<b>Delete<b>
Expand Down
10 changes: 8 additions & 2 deletions tests/test_model_deletions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import pytest

from tests.models import Department


@pytest.mark.asyncio
async def test_model_deletions(loaded_database_and_model):
Expand Down Expand Up @@ -36,8 +38,12 @@ async def test_model_deletions(loaded_database_and_model):

assert len(result) == 201

await Employees.delete_many(result)
await Employees.delete_many(result[:100])

result = await Employees.all()

assert len(result) == 0
assert len(result) == 101

await Employees.delete_filter(Employees.is_employed == True)

assert await Employees.count() == 0

0 comments on commit 5b54d6e

Please sign in to comment.