Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added bulk delete option #107

Closed
wants to merge 5 commits into from
Closed

Conversation

sinisaos
Copy link
Member

Related to #11

@codecov-commenter
Copy link

codecov-commenter commented Nov 13, 2021

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 91.04%. Comparing base (2207831) to head (909cd7f).
Report is 143 commits behind head on master.

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #107      +/-   ##
==========================================
+ Coverage   90.94%   91.04%   +0.09%     
==========================================
  Files          24       24              
  Lines        1237     1250      +13     
==========================================
+ Hits         1125     1138      +13     
  Misses        112      112              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@sinisaos
Copy link
Member Author

sinisaos commented Jan 2, 2022

@dantownsend What do you think about this? Can it be useful?

@dantownsend
Copy link
Member

@sinisaos It's definitely useful. Just need to test it locally.

@sinisaos
Copy link
Member Author

sinisaos commented Jan 2, 2022

@dantownsend Great. Thanks.

@@ -14,7 +14,7 @@ Endpoints
========== ======================= ==========================================================================================================
Path Methods Description
========== ======================= ==========================================================================================================
/ GET, POST, DELETE Get all rows, post a new row, or delete all matching rows.
/ GET, POST Get all rows or post a new row.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep DELETE here.

Comment on lines 636 to 640
self.table.delete().where(
self.table._meta.primary_key.is_in(
[int(item) for item in split_params_ids]
)
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should check if there are any valid ids before applying the filter, otherwise it will fail.

query = self.table.delete()
ids = [int(item) for item in split_params_ids]
if ids:
    query = query.where(self.table._meta.primary_key.is_in(ids))
query = self._apply_filters(query, split_params)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right! I changed the delete_bulk method to work only with filter params (e.g. name param), only with __ids param and to work together for additional safety.

try:
    query: t.Union[
        Select, Count, Objects, Delete
    ] = self.table.delete()
    try:
        # if __ids query param is not empty
        ids = [int(item) for item in split_params_ids]
        query_ids = query.where(
            self.table._meta.primary_key.is_in(ids)
        )
        query = self._apply_filters(query_ids, split_params)
    except ValueError:
        # if __ids query param is empty
        query = self._apply_filters(query, split_params)
  except MalformedQuery as exception:
    return Response(str(exception), status_code=400)

It's a little complicated but it works.

@@ -804,17 +804,19 @@ def test_no_bulk_delete(self):

def test_bulk_delete(self):
"""
Make sure that bulk deletes are only allowed is allow_bulk_delete is
True.
Make sure that bulk deletes are only allowed is ``allow_bulk_delete``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an old typo here - should be if instead of is.

Comment on lines 199 to 216
Bulk delete
-----------

To specify which records you want to delete in bulk, pass a query parameter
like this ``__ids=1,2,3``, and you be able to delete all results whose ``id``
is in the query params.

A query which delete movies with ``id`` pass in query parameter:

.. code-block::

DELETE https://demo1.piccolo-orm.com/api/tables/movie/?__ids=1,2,3

.. warning:: To be able to provide a bulk delete action, we must set
``allow_bulk_delete`` to ``True``.

-------------------------------------------------------------------------------

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good for us to expand upon these docs some more at some point. You should be able to do stuff like:

DELETE /movie/?__name=foobar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. We can write that all three methods work.

DELETE /movie/?__name=foobar (delete all movies with name foobar)
DELETE /movie/?__ids=1,2,3 (delete all movies with id 1,2,3)
DELETE /movie/?__name=foobar&__ids=1,2 (delete all movies with name foobar, but only if id is 1 or 2)

@dantownsend
Copy link
Member

@sinisaos This is a great start. I've left some comments.

@sinisaos
Copy link
Member Author

sinisaos commented Jan 3, 2022

@dantownsend I made proposed changes. Can you check it out?

@dantownsend
Copy link
Member

@sinisaos Cool, thanks for this.

I was thinking about this last night. What happens when we do DELETE /?id=1&id=2. Does this work without the __ids parameter?

What you've added is a good solution, but it's part of a wider problem - being able to specify multiple values for a filter.

Imagine we wanted to filter by name: GET /?name=StarWars&name=LordOfTheRings.

I wonder if there's some way of making this work?

If not we can do with the __ids solution, but just want to consider all options.

@sinisaos
Copy link
Member Author

sinisaos commented Jan 4, 2022

I was thinking about this last night. What happens when we do DELETE /?id=1&id=2. Does this work without the __ids parameter?

No. It doesn't work.

Imagine we wanted to filter by name: GET /?name=StarWars&name=LordOfTheRings.

and this also doesn't work due to a validation error because we can't filter with the same query params as model_dict value for name is a list, not an single value.

I wonder if there's some way of making this work?

I don't see any other way except to do the same as for __ids but for all possible filter params.

I think __ids is a convenient and easy way to pass multiple values to single query param (very similar to what we did for __visible_fields). If you know how to do it without __ids, feel free to make these changes.

@dantownsend
Copy link
Member

@sinisaos I vaguely remember being able to pass in multiple values, but I might be confusing it with something else.

Was it by doing something like: ?id[]=1,2,3?

FastAPI makes it more difficult as it expects a single integer. But maybe if the type annotation is changes to t.List[int] it could work.

I'll have a look tomorrow. It probably isn't doable, but just in case.

@sinisaos sinisaos closed this Mar 6, 2022
@sinisaos
Copy link
Member Author

sinisaos commented Mar 6, 2022

Closed - open for too long without rejection, merge or activity. Feel free to reopen PR and use it again if code is still relevant.

@dantownsend
Copy link
Member

@sinisaos All of these PRs are still relevant. I'm sorry I haven't been able to merge them in yet.

What tends to happen is a bug comes along which takes higher priority, or I don't have time to finish reviewing it.

I think moving forward there needs to be a better system around code review, so good PRs don't languish.

@sinisaos
Copy link
Member Author

sinisaos commented Mar 6, 2022

@dantownsend No worries. I know there are a lot of things that have higher priority (especially in Piccolo ORM). I closed all PRs older than 3-4 months because nothing happens in them and it makes no sense for them to be open after all code changes that have happened in the meantime. Feel free to reopen it or use it again if you find something interesting. Cheers.

@sinisaos sinisaos deleted the bulk_delete branch March 6, 2022 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants