Skip to content

Commit

Permalink
Merge branch 'master' of github.com:piccolo-orm/piccolo_api
Browse files Browse the repository at this point in the history
  • Loading branch information
dantownsend committed Apr 3, 2023
2 parents 5a1e4b7 + c0cbee8 commit ab71ef6
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 5 deletions.
7 changes: 7 additions & 0 deletions docs/source/api_reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ LoginHooks

.. autoclass:: LoginHooks

OrderBy
-------

.. currentmodule:: piccolo_api.crud.endpoints

.. autoclass:: OrderBy

CAPTCHA
-------

Expand Down
4 changes: 2 additions & 2 deletions docs/source/crud/piccolo_crud.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ A query which fetches all movies, sorted by duration:
GET /movie/?__order=duration
You can reverse the sort by prepending '-' to the field. For example:
You can reverse the sort by prepending ``'-'`` to the field. For example:

.. code-block::
GET /movie/?__order=-duration
Multiple columns can be used for the sort:
Multiple columns can be used for the sort. Just separate them with a comma:

.. code-block::
Expand Down
34 changes: 31 additions & 3 deletions piccolo_api/crud/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,38 @@ class CustomJSONResponse(Response):
media_type = "application/json"


@dataclass
class HashableDict(dict):
def __key(self):
return tuple((k, self[k]) for k in sorted(self))

def __hash__(self):
return hash(self.__key())

def __eq__(self, other):
return self.__key() == other.__key()


class OrderBy:
column: Column
ascending: bool
def __init__(self, column: Column, ascending: bool = True):
self.column = column
self.ascending = ascending

def to_dict(self) -> HashableDict:
"""
Serialise this class into something which can be converted to JSON
(used by Piccolo Admin).
"""
column = ".".join(
[i._meta.name for i in self.column._meta.call_chain]
+ [self.column._meta.name]
)
return HashableDict(column=column, ascending=self.ascending)

def __eq__(self, value: t.Any) -> bool:
if not isinstance(value, OrderBy):
return False

return self.to_dict() == value.to_dict()


@dataclass
Expand Down
37 changes: 37 additions & 0 deletions tests/crud/test_crud_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1803,3 +1803,40 @@ def test_page_sized_results(self):

response = client.get("/?__page_size=99&__page=1&__range_header=true")
self.assertEqual(response.headers.get("Content-Range"), "movie 0-2/3")


class TestOrderBy(TestCase):
def test_eq(self):
# Same column, same ascending
self.assertEqual(
OrderBy(column=Movie.name, ascending=True),
OrderBy(column=Movie.name, ascending=True),
)

# Same column, different ascending
self.assertNotEqual(
OrderBy(column=Movie.name, ascending=True),
OrderBy(column=Movie.name, ascending=False),
)

# Different column, same ascending
self.assertNotEqual(
OrderBy(column=Movie.name, ascending=True),
OrderBy(column=Movie.id, ascending=True),
)

def test_to_dict(self):
self.assertDictEqual(
OrderBy(column=Movie.name, ascending=True).to_dict(),
{"column": "name", "ascending": True},
)

self.assertDictEqual(
OrderBy(column=Role.movie.name, ascending=True).to_dict(),
{"column": "movie.name", "ascending": True},
)

self.assertDictEqual(
OrderBy(column=Role.movie.name, ascending=False).to_dict(),
{"column": "movie.name", "ascending": False},
)

0 comments on commit ab71ef6

Please sign in to comment.