auto-rest-api 0.1.2__py3-none-any.whl → 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-rest-api might be problematic. Click here for more details.
- auto_rest/handlers.py +15 -7
- auto_rest/interfaces.py +41 -52
- auto_rest/queries.py +62 -1
- {auto_rest_api-0.1.2.dist-info → auto_rest_api-0.1.3.dist-info}/METADATA +1 -1
- auto_rest_api-0.1.3.dist-info/RECORD +14 -0
- auto_rest/params.py +0 -174
- auto_rest_api-0.1.2.dist-info/RECORD +0 -15
- {auto_rest_api-0.1.2.dist-info → auto_rest_api-0.1.3.dist-info}/LICENSE.md +0 -0
- {auto_rest_api-0.1.2.dist-info → auto_rest_api-0.1.3.dist-info}/WHEEL +0 -0
- {auto_rest_api-0.1.2.dist-info → auto_rest_api-0.1.3.dist-info}/entry_points.txt +0 -0
auto_rest/handlers.py
CHANGED
|
@@ -51,16 +51,15 @@ This makes it easy to incorporate handlers into a FastAPI application.
|
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
53
|
import logging
|
|
54
|
-
from typing import Awaitable, Callable
|
|
54
|
+
from typing import Awaitable, Callable, Literal, Optional
|
|
55
55
|
|
|
56
|
-
from fastapi import Depends, Response
|
|
56
|
+
from fastapi import Depends, Query, Response
|
|
57
57
|
from pydantic import create_model
|
|
58
58
|
from pydantic.main import BaseModel as PydanticModel
|
|
59
59
|
from sqlalchemy import insert, MetaData, select, Table
|
|
60
60
|
|
|
61
61
|
from .interfaces import *
|
|
62
62
|
from .models import *
|
|
63
|
-
from .params import *
|
|
64
63
|
from .queries import *
|
|
65
64
|
|
|
66
65
|
__all__ = [
|
|
@@ -192,21 +191,30 @@ def create_list_records_handler(engine: DBEngine, table: Table) -> Callable[...,
|
|
|
192
191
|
"""
|
|
193
192
|
|
|
194
193
|
interface = create_interface(table)
|
|
194
|
+
interface_opt = create_interface(table, mode="optional")
|
|
195
|
+
columns = tuple(table.columns.keys())
|
|
195
196
|
|
|
196
197
|
async def list_records_handler(
|
|
197
198
|
response: Response,
|
|
198
199
|
session: DBSession = Depends(create_session_iterator(engine)),
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
_limit_: int = Query(0, ge=0, description="The maximum number of records to return."),
|
|
201
|
+
_offset_: int = Query(0, ge=0, description="The starting index of the returned records."),
|
|
202
|
+
_order_by_: Optional[Literal[*columns]] = Query(None, description="The field name to sort by."),
|
|
203
|
+
_direction_: Literal["asc", "desc"] = Query("asc", description="Sort results in 'asc' or 'desc' order.")
|
|
201
204
|
) -> list[interface]:
|
|
202
205
|
"""Fetch a list of records from the database.
|
|
203
206
|
|
|
204
207
|
URL query parameters are used to enable filtering, ordering, and paginating returned values.
|
|
205
208
|
"""
|
|
206
209
|
|
|
210
|
+
response.headers["X-Pagination-Limit"] = str(_limit_)
|
|
211
|
+
response.headers["X-Pagination-Offset"] = str(_offset_)
|
|
212
|
+
response.headers["X-Order-By"] = str(_order_by_)
|
|
213
|
+
response.headers["X-Order-Direction"] = str(_direction_)
|
|
214
|
+
|
|
207
215
|
query = select(table)
|
|
208
|
-
query = apply_pagination_params(query,
|
|
209
|
-
query = apply_ordering_params(query,
|
|
216
|
+
query = apply_pagination_params(query, _limit_, _offset_)
|
|
217
|
+
query = apply_ordering_params(query, _order_by_, _direction_)
|
|
210
218
|
|
|
211
219
|
result = await execute_session_query(session, query)
|
|
212
220
|
return [row._mapping for row in result.all()]
|
auto_rest/interfaces.py
CHANGED
|
@@ -10,21 +10,20 @@ which force interface fields to be optional or read only.
|
|
|
10
10
|
based on a SQLAlchemy table.
|
|
11
11
|
|
|
12
12
|
```python
|
|
13
|
-
default_interface =
|
|
14
|
-
required_interface =
|
|
15
|
-
optional_interface =
|
|
13
|
+
default_interface = create_interface(database_model)
|
|
14
|
+
required_interface = create_interface(database_model, mode="required")
|
|
15
|
+
optional_interface = create_interface(database_model, mode="optional")
|
|
16
16
|
```
|
|
17
17
|
"""
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
from typing import Any, Iterator, Literal
|
|
19
20
|
|
|
20
21
|
from pydantic import BaseModel as PydanticModel, create_model
|
|
21
22
|
from sqlalchemy import Column, Table
|
|
22
23
|
|
|
23
24
|
__all__ = ["create_interface"]
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
MODES = Literal["default", "required", "optional"]
|
|
26
|
+
MODE_TYPE = Literal["default", "required", "optional"]
|
|
28
27
|
|
|
29
28
|
|
|
30
29
|
def iter_columns(table: Table, pk_only: bool = False) -> Iterator[Column]:
|
|
@@ -38,69 +37,62 @@ def iter_columns(table: Table, pk_only: bool = False) -> Iterator[Column]:
|
|
|
38
37
|
A column of the SQLAlchemy model.
|
|
39
38
|
"""
|
|
40
39
|
|
|
41
|
-
for column in table.columns:
|
|
40
|
+
for column in table.columns.values():
|
|
42
41
|
if column.primary_key or not pk_only:
|
|
43
42
|
yield column
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
def
|
|
47
|
-
"""Return the
|
|
48
|
-
|
|
49
|
-
Returns the `any` type for DBMS drivers that do not support mapping DB
|
|
50
|
-
types to Python primitives,
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
col: The column to determine a type for.
|
|
45
|
+
def create_field_definition(col: Column, mode: MODE_TYPE = "default") -> tuple[type[any], any]:
|
|
46
|
+
"""Return a tuple with the type and default value for a database table column.
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
return col.type.python_type
|
|
48
|
+
The returned tuple is compatible for use with Pydantic as a field definition
|
|
49
|
+
during dynamic model generation. The `mode` argument modifies returned
|
|
50
|
+
values to enforce different behavior in the generated Pydantic interface.
|
|
61
51
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def get_column_default(col: Column, mode: MODES) -> any:
|
|
68
|
-
"""Return the default value for a column.
|
|
52
|
+
Modes:
|
|
53
|
+
default: Values are marked as (not)required based on the column schema.
|
|
54
|
+
required: Values are always marked required.
|
|
55
|
+
required: Values are always marked optional.
|
|
69
56
|
|
|
70
57
|
Args:
|
|
71
|
-
col: The column to
|
|
58
|
+
col: The column to return values for.
|
|
72
59
|
mode: The mode to use when determining the default value.
|
|
73
60
|
|
|
74
61
|
Returns:
|
|
75
62
|
The default value for the column.
|
|
76
63
|
"""
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
try:
|
|
66
|
+
col_type = col.type.python_type
|
|
67
|
+
|
|
68
|
+
except NotImplementedError:
|
|
69
|
+
col_type = Any
|
|
70
|
+
|
|
71
|
+
col_default = getattr(col.default, "arg", col.default)
|
|
81
72
|
|
|
82
73
|
if mode == "required":
|
|
83
|
-
return ...
|
|
74
|
+
return col_type, ...
|
|
84
75
|
|
|
85
76
|
elif mode == "optional":
|
|
86
|
-
return
|
|
77
|
+
return col_type | None, col_default
|
|
87
78
|
|
|
88
|
-
elif mode == "default":
|
|
89
|
-
|
|
90
|
-
return default
|
|
79
|
+
elif mode == "default" and (col.nullable or col.default):
|
|
80
|
+
return col_type | None, col_default
|
|
91
81
|
|
|
92
|
-
|
|
82
|
+
elif mode == "default":
|
|
83
|
+
return col_type, ...
|
|
93
84
|
|
|
94
85
|
raise RuntimeError(f"Unknown mode: {mode}")
|
|
95
86
|
|
|
96
87
|
|
|
97
|
-
def create_interface(
|
|
98
|
-
table: Table,
|
|
99
|
-
pk_only: bool = False,
|
|
100
|
-
mode: MODES = "default"
|
|
101
|
-
) -> type[PydanticModel]:
|
|
88
|
+
def create_interface(table: Table, pk_only: bool = False, mode: MODE_TYPE = "default") -> type[PydanticModel]:
|
|
102
89
|
"""Create a Pydantic interface for a SQLAlchemy model where all fields are required.
|
|
103
90
|
|
|
91
|
+
Modes:
|
|
92
|
+
default: Values are marked as (not)required based on the column schema.
|
|
93
|
+
required: Values are always marked required.
|
|
94
|
+
required: Values are always marked optional.
|
|
95
|
+
|
|
104
96
|
Args:
|
|
105
97
|
table: The SQLAlchemy table to create an interface for.
|
|
106
98
|
pk_only: If True, only include primary key columns.
|
|
@@ -111,16 +103,13 @@ def create_interface(
|
|
|
111
103
|
"""
|
|
112
104
|
|
|
113
105
|
# Map field names to the column type and default value.
|
|
114
|
-
columns = iter_columns(table, pk_only)
|
|
115
106
|
fields = {
|
|
116
|
-
col.name: (
|
|
117
|
-
for col in columns
|
|
107
|
+
col.name: create_field_definition(col, mode) for col in iter_columns(table, pk_only)
|
|
118
108
|
}
|
|
119
109
|
|
|
120
|
-
#
|
|
121
|
-
|
|
110
|
+
# Create a unique name for the interface
|
|
111
|
+
name = f"{table.name}-{mode.title()}"
|
|
122
112
|
if pk_only:
|
|
123
|
-
|
|
113
|
+
name += '-PK'
|
|
124
114
|
|
|
125
|
-
|
|
126
|
-
return create_model(interface_name, **fields)
|
|
115
|
+
return create_model(name, __config__={'arbitrary_types_allowed': True}, **fields)
|
auto_rest/queries.py
CHANGED
|
@@ -19,15 +19,18 @@ handling and provides a streamlined interface for database interactions.
|
|
|
19
19
|
result = await execute_session_query(async_session, query)
|
|
20
20
|
```
|
|
21
21
|
"""
|
|
22
|
+
from typing import Literal
|
|
22
23
|
|
|
23
24
|
from fastapi import HTTPException
|
|
24
|
-
from sqlalchemy import Executable, Result
|
|
25
|
+
from sqlalchemy import asc, desc, Executable, Result, Select
|
|
25
26
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
26
27
|
from starlette import status
|
|
27
28
|
|
|
28
29
|
from auto_rest.models import DBSession
|
|
29
30
|
|
|
30
31
|
__all__ = [
|
|
32
|
+
"apply_ordering_params",
|
|
33
|
+
"apply_pagination_params",
|
|
31
34
|
"commit_session",
|
|
32
35
|
"delete_session_record",
|
|
33
36
|
"execute_session_query",
|
|
@@ -35,6 +38,64 @@ __all__ = [
|
|
|
35
38
|
]
|
|
36
39
|
|
|
37
40
|
|
|
41
|
+
def apply_ordering_params(
|
|
42
|
+
query: Select,
|
|
43
|
+
order_by: str | None = None,
|
|
44
|
+
direction: Literal["desc", "asc"] = "asc"
|
|
45
|
+
) -> Select:
|
|
46
|
+
"""Apply ordering to a database query.
|
|
47
|
+
|
|
48
|
+
Returns a copy of the provided query with ordering parameters applied.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
query: The database query to apply parameters to.
|
|
52
|
+
order_by: The name of the column to order by.
|
|
53
|
+
direction: The direction to order by (defaults to "asc").
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
A copy of the query modified to return ordered values.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
if order_by is None:
|
|
60
|
+
return query
|
|
61
|
+
|
|
62
|
+
if order_by not in query.columns:
|
|
63
|
+
raise ValueError(f"Invalid column name: {order_by}")
|
|
64
|
+
|
|
65
|
+
# Default to ascending order for an invalid ordering direction
|
|
66
|
+
if direction == "desc":
|
|
67
|
+
return query.order_by(desc(order_by))
|
|
68
|
+
|
|
69
|
+
elif direction == "asc":
|
|
70
|
+
return query.order_by(asc(order_by))
|
|
71
|
+
|
|
72
|
+
raise ValueError(f"Invalid direction, use 'asc' or 'desc': {direction}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def apply_pagination_params(query: Select, limit: int = 0, offset: int = 0) -> Select:
|
|
76
|
+
"""Apply pagination to a database query.
|
|
77
|
+
|
|
78
|
+
Returns a copy of the provided query with offset and limit parameters applied.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
query: The database query to apply parameters to.
|
|
82
|
+
limit: The number of results to return.
|
|
83
|
+
offset: The offset to start with.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
A copy of the query modified to only return the paginated values.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
if offset < 0 or limit < 0:
|
|
90
|
+
raise ValueError("Pagination parameters cannot be negative")
|
|
91
|
+
|
|
92
|
+
# Do not apply pagination if not requested
|
|
93
|
+
if limit == 0:
|
|
94
|
+
return query
|
|
95
|
+
|
|
96
|
+
return query.offset(offset or 0).limit(limit)
|
|
97
|
+
|
|
98
|
+
|
|
38
99
|
async def commit_session(session: DBSession) -> None:
|
|
39
100
|
"""Commit a SQLAlchemy session.
|
|
40
101
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
auto_rest/__init__.py,sha256=9ICmv2urSoAo856FJylKdorF19UsUGc4eyORYLptf1Q,69
|
|
2
|
+
auto_rest/__main__.py,sha256=lz6-LEpbu51Ah3QCzUzZhevjWhK5kmOxhuuqhX5t-io,3093
|
|
3
|
+
auto_rest/app.py,sha256=I6ZeHzKuhPTS1svLhMTvefjzTkMJgGpwVz1kdJ_9mtE,1887
|
|
4
|
+
auto_rest/cli.py,sha256=A7-kMTNNzqZB7jTUJBAVqfYm9RyYjENr0g_vK9JE0N4,5199
|
|
5
|
+
auto_rest/handlers.py,sha256=Z8DMv3KRYLBXlUKoE4e-2qE9YvG-IPgS57C0RpUDWv4,12603
|
|
6
|
+
auto_rest/interfaces.py,sha256=WB_0eMDjGF8DpnDN9INHqo7u4x3aklvzAYK4t3JwC7s,3779
|
|
7
|
+
auto_rest/models.py,sha256=HCJUQPBmkkfVFv9CRcPzMP66pQk_UIb3j3cdwHqodwE,5388
|
|
8
|
+
auto_rest/queries.py,sha256=Z2ATkcSYldV6BkcrmLogmBoDkPEkyFzFqI7qPcq86uc,4705
|
|
9
|
+
auto_rest/routers.py,sha256=RqBwLqVFU1OIFSCUuwOtTis8mT_zyWTaB_8SyIXjfe0,5727
|
|
10
|
+
auto_rest_api-0.1.3.dist-info/LICENSE.md,sha256=zFRw_u1mGSOH8GrpOu0L1P765aX9fB5UpKz06mTxAos,34893
|
|
11
|
+
auto_rest_api-0.1.3.dist-info/METADATA,sha256=Cs7u-2jZGTTlvBprPzdLVWl1uSAAjjLgeh5PuHo3tUk,2951
|
|
12
|
+
auto_rest_api-0.1.3.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
13
|
+
auto_rest_api-0.1.3.dist-info/entry_points.txt,sha256=zFynmBrHyYo3Ds0Uo4-bTFe1Tdr5mIXV4dPQOFb-W1w,53
|
|
14
|
+
auto_rest_api-0.1.3.dist-info/RECORD,,
|
auto_rest/params.py
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The `params` module provides utilities for extracting and applying query
|
|
3
|
-
parameters from incoming HTTP requests. These utilities ensure the consistent
|
|
4
|
-
parsing, validation, and application of query parameters, and automatically
|
|
5
|
-
update HTTP response headers to reflect applied query options.
|
|
6
|
-
|
|
7
|
-
Parameter functions are designed in pairs of two. The first function is a
|
|
8
|
-
factory for creating an injectable FastAPI dependency. The dependency
|
|
9
|
-
is used to parse parameters from incoming requests and applies high level
|
|
10
|
-
validation against the parsed values. The second function to applies the
|
|
11
|
-
validated arguments onto a SQLAlchemy query and returns the updated query.
|
|
12
|
-
|
|
13
|
-
!!! example "Example: Parameter Parsing and Application"
|
|
14
|
-
|
|
15
|
-
```python
|
|
16
|
-
from fastapi import FastAPI, Response
|
|
17
|
-
from sqlalchemy import select
|
|
18
|
-
from auto_rest.query_params import create_pagination_dependency, apply_pagination_params
|
|
19
|
-
|
|
20
|
-
app = FastAPI()
|
|
21
|
-
|
|
22
|
-
@app.get("/items/")
|
|
23
|
-
async def list_items(
|
|
24
|
-
pagination_params: dict = create_pagination_dependency(model),
|
|
25
|
-
response: Response
|
|
26
|
-
):
|
|
27
|
-
query = select(model)
|
|
28
|
-
query = apply_pagination_params(query, pagination_params, response)
|
|
29
|
-
return ... # Logic to further process and execute the query goes here
|
|
30
|
-
```
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
from collections.abc import Callable
|
|
34
|
-
from typing import Literal, Optional
|
|
35
|
-
|
|
36
|
-
from fastapi import Depends, Query
|
|
37
|
-
from sqlalchemy import asc, desc, Table
|
|
38
|
-
from sqlalchemy.sql.selectable import Select
|
|
39
|
-
from starlette.responses import Response
|
|
40
|
-
|
|
41
|
-
__all__ = [
|
|
42
|
-
"apply_ordering_params",
|
|
43
|
-
"apply_pagination_params",
|
|
44
|
-
"create_ordering_dependency",
|
|
45
|
-
"create_pagination_dependency",
|
|
46
|
-
]
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def create_ordering_dependency(table: Table) -> Callable[..., dict]:
|
|
50
|
-
"""Create an injectable dependency for fetching ordering arguments from query parameters.
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
table: The database table to create the dependency for.
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
An injectable FastAPI dependency.
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
columns = tuple(table.columns.keys())
|
|
60
|
-
|
|
61
|
-
def get_ordering_params(
|
|
62
|
-
_order_by_: Optional[Literal[*columns]] = Query(None, description="The field name to sort by."),
|
|
63
|
-
_direction_: Optional[Literal["asc", "desc"]] = Query(None, description="Sort results in 'asc' or 'desc' order.")
|
|
64
|
-
) -> dict:
|
|
65
|
-
"""Extract ordering parameters from request query parameters.
|
|
66
|
-
|
|
67
|
-
Args:
|
|
68
|
-
_order_by_: The field to order by.
|
|
69
|
-
_direction_: The direction to order by.
|
|
70
|
-
|
|
71
|
-
Returns:
|
|
72
|
-
dict: A dictionary containing the `order_by` and `direction` values.
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
return {"order_by": _order_by_, "direction": _direction_}
|
|
76
|
-
|
|
77
|
-
return Depends(get_ordering_params)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def apply_ordering_params(query: Select, params: dict, response: Response) -> Select:
|
|
81
|
-
"""Apply ordering to a database query.
|
|
82
|
-
|
|
83
|
-
Returns a copy of the provided query with ordering parameters applied.
|
|
84
|
-
This method is compatible with parameters returned by the `get_ordering_params` method.
|
|
85
|
-
Ordering is not applied for invalid params, but response headers are still set.
|
|
86
|
-
|
|
87
|
-
Args:
|
|
88
|
-
query: The database query to apply parameters to.
|
|
89
|
-
params: A dictionary containing parsed URL parameters.
|
|
90
|
-
response: The outgoing HTTP response object.
|
|
91
|
-
|
|
92
|
-
Returns:
|
|
93
|
-
A copy of the query modified to return ordered values.
|
|
94
|
-
"""
|
|
95
|
-
|
|
96
|
-
order_by = params.get("order_by")
|
|
97
|
-
direction = params.get("direction")
|
|
98
|
-
|
|
99
|
-
# Set common response headers
|
|
100
|
-
response.headers["X-Order-By"] = str(order_by)
|
|
101
|
-
response.headers["X-Order-Direction"] = str(direction)
|
|
102
|
-
|
|
103
|
-
if order_by is None:
|
|
104
|
-
response.headers["X-Order-Applied"] = "false"
|
|
105
|
-
return query
|
|
106
|
-
|
|
107
|
-
# Default to ascending order for an invalid ordering direction
|
|
108
|
-
response.headers["X-Order-Applied"] = "true"
|
|
109
|
-
if direction == "desc":
|
|
110
|
-
return query.order_by(desc(order_by))
|
|
111
|
-
|
|
112
|
-
else:
|
|
113
|
-
return query.order_by(asc(order_by))
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def create_pagination_dependency(table: Table) -> Callable[..., dict]:
|
|
117
|
-
"""Create an injectable dependency for fetching pagination arguments from query parameters.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
table: The database table to create the dependency for.
|
|
121
|
-
|
|
122
|
-
Returns:
|
|
123
|
-
An injectable FastAPI dependency.
|
|
124
|
-
"""
|
|
125
|
-
|
|
126
|
-
def get_pagination_params(
|
|
127
|
-
_limit_: Optional[int] = Query(None, ge=0, description="The maximum number of records to return."),
|
|
128
|
-
_offset_: Optional[int] = Query(None, ge=0, description="The starting index of the returned records."),
|
|
129
|
-
) -> dict[str, int]:
|
|
130
|
-
"""Extract pagination parameters from request query parameters.
|
|
131
|
-
|
|
132
|
-
Args:
|
|
133
|
-
_limit_: The maximum number of records to return.
|
|
134
|
-
_offset_: The starting index of the returned records.
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
dict: A dictionary containing the `limit` and `offset` values.
|
|
138
|
-
"""
|
|
139
|
-
|
|
140
|
-
return {"limit": _limit_, "offset": _offset_}
|
|
141
|
-
|
|
142
|
-
return Depends(get_pagination_params)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def apply_pagination_params(query: Select, params: dict[str, int], response: Response) -> Select:
|
|
146
|
-
"""Apply pagination to a database query.
|
|
147
|
-
|
|
148
|
-
Returns a copy of the provided query with offset and limit parameters applied.
|
|
149
|
-
This method is compatible with parameters returned by the `get_pagination_params` method.
|
|
150
|
-
Pagination is not applied for invalid params, but response headers are still set.
|
|
151
|
-
|
|
152
|
-
Args:
|
|
153
|
-
query: The database query to apply parameters to.
|
|
154
|
-
params: A dictionary containing parsed URL parameters.
|
|
155
|
-
response: The outgoing HTTP response object.
|
|
156
|
-
|
|
157
|
-
Returns:
|
|
158
|
-
A copy of the query modified to only return the paginated values.
|
|
159
|
-
"""
|
|
160
|
-
|
|
161
|
-
limit = params.get("limit")
|
|
162
|
-
offset = params.get("offset")
|
|
163
|
-
|
|
164
|
-
# Set common response headers
|
|
165
|
-
response.headers["X-Pagination-Limit"] = str(limit)
|
|
166
|
-
response.headers["X-Pagination-Offset"] = str(offset)
|
|
167
|
-
|
|
168
|
-
# Do not apply pagination if not requested
|
|
169
|
-
if limit in (0, None):
|
|
170
|
-
response.headers["X-Pagination-Applied"] = "false"
|
|
171
|
-
return query
|
|
172
|
-
|
|
173
|
-
response.headers["X-Pagination-Applied"] = "true"
|
|
174
|
-
return query.offset(offset or 0).limit(limit)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
auto_rest/__init__.py,sha256=9ICmv2urSoAo856FJylKdorF19UsUGc4eyORYLptf1Q,69
|
|
2
|
-
auto_rest/__main__.py,sha256=lz6-LEpbu51Ah3QCzUzZhevjWhK5kmOxhuuqhX5t-io,3093
|
|
3
|
-
auto_rest/app.py,sha256=I6ZeHzKuhPTS1svLhMTvefjzTkMJgGpwVz1kdJ_9mtE,1887
|
|
4
|
-
auto_rest/cli.py,sha256=A7-kMTNNzqZB7jTUJBAVqfYm9RyYjENr0g_vK9JE0N4,5199
|
|
5
|
-
auto_rest/handlers.py,sha256=84P7mEXzwpEgSOg6ZIBMT_q0ZTfiESpd-IXUmekMqJo,12005
|
|
6
|
-
auto_rest/interfaces.py,sha256=U2-e3fy_ROmNrIAvkXG7dACMJi3akFEldXrbIacMbIc,3714
|
|
7
|
-
auto_rest/models.py,sha256=HCJUQPBmkkfVFv9CRcPzMP66pQk_UIb3j3cdwHqodwE,5388
|
|
8
|
-
auto_rest/params.py,sha256=t1YK9Q-dwh7N99myYH2RZCO6XheWcgLJl_Stpi65PKQ,6075
|
|
9
|
-
auto_rest/queries.py,sha256=nws0J1XnCzB3Y0DN1dDccsgK91z7dzza1VyC_qCitG0,2910
|
|
10
|
-
auto_rest/routers.py,sha256=RqBwLqVFU1OIFSCUuwOtTis8mT_zyWTaB_8SyIXjfe0,5727
|
|
11
|
-
auto_rest_api-0.1.2.dist-info/LICENSE.md,sha256=zFRw_u1mGSOH8GrpOu0L1P765aX9fB5UpKz06mTxAos,34893
|
|
12
|
-
auto_rest_api-0.1.2.dist-info/METADATA,sha256=xQY6_P1nDZbq6PfcDp5EGjEhRxCwJql_g8V0NcRpxVM,2951
|
|
13
|
-
auto_rest_api-0.1.2.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
14
|
-
auto_rest_api-0.1.2.dist-info/entry_points.txt,sha256=zFynmBrHyYo3Ds0Uo4-bTFe1Tdr5mIXV4dPQOFb-W1w,53
|
|
15
|
-
auto_rest_api-0.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|