fastapi-extended-query-method 0.0.32__tar.gz → 0.0.33__tar.gz
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.
- fastapi_extended_query_method-0.0.33/PKG-INFO +206 -0
- fastapi_extended_query_method-0.0.33/README.md +179 -0
- fastapi_extended_query_method-0.0.33/src/fastapi_extended_query_method.egg-info/PKG-INFO +206 -0
- fastapi_extended_query_method-0.0.32/PKG-INFO +0 -110
- fastapi_extended_query_method-0.0.32/README.md +0 -83
- fastapi_extended_query_method-0.0.32/src/fastapi_extended_query_method.egg-info/PKG-INFO +0 -110
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/LICENSE +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/setup.cfg +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/setup.py +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/src/fastapi_extended_query_method.egg-info/SOURCES.txt +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/src/fastapi_extended_query_method.egg-info/dependency_links.txt +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/src/fastapi_extended_query_method.egg-info/requires.txt +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/src/fastapi_extended_query_method.egg-info/top_level.txt +0 -0
- {fastapi_extended_query_method-0.0.32 → fastapi_extended_query_method-0.0.33}/src/fastapi_extended_query_method.py +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-extended-query-method
|
|
3
|
+
Version: 0.0.33
|
|
4
|
+
Summary: Native HTTP QUERY method support for FastAPI with automatic cache control and Swagger compatibility.
|
|
5
|
+
Home-page: https://github.com/JorgeCardona/fastapi-extended-query-method
|
|
6
|
+
Author: Jorge Cardona
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: fastapi>=0.139.0
|
|
14
|
+
Requires-Dist: uvicorn>=0.5.1
|
|
15
|
+
Requires-Dist: requests>=2.34.2
|
|
16
|
+
Requires-Dist: requests-cache>=1.3.3
|
|
17
|
+
Requires-Dist: tabulate>=0.10.0
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# FastAPI Extended Query Method
|
|
29
|
+
|
|
30
|
+
Native HTTP QUERY support for FastAPI.
|
|
31
|
+
|
|
32
|
+
## Overview
|
|
33
|
+
|
|
34
|
+
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
35
|
+
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
``` bash
|
|
40
|
+
pip install fastapi-extended-query-method
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
``` python
|
|
46
|
+
import uuid
|
|
47
|
+
from typing import List, Optional
|
|
48
|
+
import uvicorn
|
|
49
|
+
from fastapi import Query
|
|
50
|
+
from fastapi.responses import JSONResponse
|
|
51
|
+
from pydantic import BaseModel
|
|
52
|
+
|
|
53
|
+
# 1. Initialize the app using your custom class
|
|
54
|
+
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
55
|
+
|
|
56
|
+
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
57
|
+
|
|
58
|
+
# 2. Mock Data for quick testing
|
|
59
|
+
MOCK_PRODUCTS = [
|
|
60
|
+
{"id": 1, "name": "Gaming Laptop", "category": "electronics", "price": 1200.99},
|
|
61
|
+
{"id": 2, "name": "Smartphone", "category": "electronics", "price": 599.99},
|
|
62
|
+
{"id": 3, "name": "Bluetooth Headphones", "category": "electronics", "price": 79.90},
|
|
63
|
+
{"id": 4, "name": "Espresso Machine", "category": "appliances", "price": 150.00},
|
|
64
|
+
{"id": 5, "name": "Blender", "category": "appliances", "price": 45.50},
|
|
65
|
+
{"id": 6, "name": "Office Chair", "category": "furniture", "price": 180.00},
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# 3. Pydantic Schemas
|
|
69
|
+
class SearchFilters(BaseModel):
|
|
70
|
+
category: Optional[str] = None
|
|
71
|
+
min_price: Optional[float] = None
|
|
72
|
+
max_price: Optional[float] = None
|
|
73
|
+
|
|
74
|
+
class ProductSchema(BaseModel):
|
|
75
|
+
id: int
|
|
76
|
+
name: str
|
|
77
|
+
category: str
|
|
78
|
+
price: float
|
|
79
|
+
|
|
80
|
+
class SearchResponse(BaseModel):
|
|
81
|
+
status: str
|
|
82
|
+
execution_id: str
|
|
83
|
+
total_found: int
|
|
84
|
+
products: List[ProductSchema]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# 4. Filter function simulating database queries with mock data
|
|
88
|
+
def get_products_from_sqlite(filters: SearchFilters, limit: int, order_by: str):
|
|
89
|
+
results = MOCK_PRODUCTS.copy()
|
|
90
|
+
|
|
91
|
+
# Apply search filters if they are provided
|
|
92
|
+
if filters.category:
|
|
93
|
+
results = [p for p in results if p["category"].lower() == filters.category.lower()]
|
|
94
|
+
|
|
95
|
+
if filters.min_price is not None:
|
|
96
|
+
results = [p for p in results if p["price"] >= filters.min_price]
|
|
97
|
+
|
|
98
|
+
if filters.max_price is not None:
|
|
99
|
+
results = [p for p in results if p["price"] <= filters.max_price]
|
|
100
|
+
|
|
101
|
+
# Sort results dynamically (defaults to "id")
|
|
102
|
+
results = sorted(results, key=lambda x: x.get(order_by, x["id"]))
|
|
103
|
+
|
|
104
|
+
# Apply limit
|
|
105
|
+
return results[:limit]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# 5. Endpoint using your custom @app.query decorator
|
|
109
|
+
@app.query("/products/filter", response_model=SearchResponse)
|
|
110
|
+
async def filter_products(
|
|
111
|
+
filters: SearchFilters,
|
|
112
|
+
limit: int = Query(default=10, ge=1),
|
|
113
|
+
order_by: str = "id",
|
|
114
|
+
):
|
|
115
|
+
# Fetch and filter the mock data
|
|
116
|
+
filtered_products = get_products_from_sqlite(
|
|
117
|
+
filters=filters,
|
|
118
|
+
limit=limit,
|
|
119
|
+
order_by=order_by,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
execution_id = str(uuid.uuid4())
|
|
123
|
+
|
|
124
|
+
return JSONResponse(
|
|
125
|
+
content={
|
|
126
|
+
"status": "success",
|
|
127
|
+
"execution_id": execution_id,
|
|
128
|
+
"total_found": len(filtered_products),
|
|
129
|
+
"products": filtered_products,
|
|
130
|
+
},
|
|
131
|
+
headers={
|
|
132
|
+
"X-Execution-Id": execution_id,
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# 6. Direct startup block
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
uvicorn.run(
|
|
140
|
+
"main:app",
|
|
141
|
+
host="127.0.0.1",
|
|
142
|
+
port=8000,
|
|
143
|
+
reload=True,
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Swagger compatibility
|
|
148
|
+
|
|
149
|
+
After starting the application:
|
|
150
|
+
|
|
151
|
+
http://localhost:8000/docs
|
|
152
|
+
|
|
153
|
+
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
154
|
+
|
|
155
|
+
For that reason this package automatically exposes QUERY endpoints as
|
|
156
|
+
both:
|
|
157
|
+
|
|
158
|
+
- QUERY
|
|
159
|
+
- POST
|
|
160
|
+
|
|
161
|
+
Use the **POST** operation in Swagger only for interactive testing.
|
|
162
|
+
|
|
163
|
+
Real clients should invoke the QUERY method directly.
|
|
164
|
+
|
|
165
|
+
<p align="center">
|
|
166
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
167
|
+
</p>
|
|
168
|
+
|
|
169
|
+
## Cache
|
|
170
|
+
|
|
171
|
+
`query_saving_cache=True` allows caching.
|
|
172
|
+
|
|
173
|
+
`query_saving_cache=False` automatically adds:
|
|
174
|
+
|
|
175
|
+
- Cache-Control: no-store
|
|
176
|
+
- Pragma: no-cache
|
|
177
|
+
- Expires: 0
|
|
178
|
+
|
|
179
|
+
## Testing API
|
|
180
|
+
|
|
181
|
+
``` bash
|
|
182
|
+
python validate_data/test_api_query_method.py
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
<p align="center">
|
|
186
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
187
|
+
</p>
|
|
188
|
+
|
|
189
|
+
## Testing Cache
|
|
190
|
+
|
|
191
|
+
### Using Cache Stored
|
|
192
|
+
``` bash
|
|
193
|
+
python validate_data/test_cache_comparison.py
|
|
194
|
+
```
|
|
195
|
+
<p align="center">
|
|
196
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
197
|
+
</p>
|
|
198
|
+
|
|
199
|
+
### NO Using Cache Stored
|
|
200
|
+
<p align="center">
|
|
201
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
202
|
+
</p>
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# FastAPI Extended Query Method
|
|
2
|
+
|
|
3
|
+
Native HTTP QUERY support for FastAPI.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
8
|
+
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
``` bash
|
|
13
|
+
pip install fastapi-extended-query-method
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
``` python
|
|
19
|
+
import uuid
|
|
20
|
+
from typing import List, Optional
|
|
21
|
+
import uvicorn
|
|
22
|
+
from fastapi import Query
|
|
23
|
+
from fastapi.responses import JSONResponse
|
|
24
|
+
from pydantic import BaseModel
|
|
25
|
+
|
|
26
|
+
# 1. Initialize the app using your custom class
|
|
27
|
+
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
28
|
+
|
|
29
|
+
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
30
|
+
|
|
31
|
+
# 2. Mock Data for quick testing
|
|
32
|
+
MOCK_PRODUCTS = [
|
|
33
|
+
{"id": 1, "name": "Gaming Laptop", "category": "electronics", "price": 1200.99},
|
|
34
|
+
{"id": 2, "name": "Smartphone", "category": "electronics", "price": 599.99},
|
|
35
|
+
{"id": 3, "name": "Bluetooth Headphones", "category": "electronics", "price": 79.90},
|
|
36
|
+
{"id": 4, "name": "Espresso Machine", "category": "appliances", "price": 150.00},
|
|
37
|
+
{"id": 5, "name": "Blender", "category": "appliances", "price": 45.50},
|
|
38
|
+
{"id": 6, "name": "Office Chair", "category": "furniture", "price": 180.00},
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
# 3. Pydantic Schemas
|
|
42
|
+
class SearchFilters(BaseModel):
|
|
43
|
+
category: Optional[str] = None
|
|
44
|
+
min_price: Optional[float] = None
|
|
45
|
+
max_price: Optional[float] = None
|
|
46
|
+
|
|
47
|
+
class ProductSchema(BaseModel):
|
|
48
|
+
id: int
|
|
49
|
+
name: str
|
|
50
|
+
category: str
|
|
51
|
+
price: float
|
|
52
|
+
|
|
53
|
+
class SearchResponse(BaseModel):
|
|
54
|
+
status: str
|
|
55
|
+
execution_id: str
|
|
56
|
+
total_found: int
|
|
57
|
+
products: List[ProductSchema]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# 4. Filter function simulating database queries with mock data
|
|
61
|
+
def get_products_from_sqlite(filters: SearchFilters, limit: int, order_by: str):
|
|
62
|
+
results = MOCK_PRODUCTS.copy()
|
|
63
|
+
|
|
64
|
+
# Apply search filters if they are provided
|
|
65
|
+
if filters.category:
|
|
66
|
+
results = [p for p in results if p["category"].lower() == filters.category.lower()]
|
|
67
|
+
|
|
68
|
+
if filters.min_price is not None:
|
|
69
|
+
results = [p for p in results if p["price"] >= filters.min_price]
|
|
70
|
+
|
|
71
|
+
if filters.max_price is not None:
|
|
72
|
+
results = [p for p in results if p["price"] <= filters.max_price]
|
|
73
|
+
|
|
74
|
+
# Sort results dynamically (defaults to "id")
|
|
75
|
+
results = sorted(results, key=lambda x: x.get(order_by, x["id"]))
|
|
76
|
+
|
|
77
|
+
# Apply limit
|
|
78
|
+
return results[:limit]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# 5. Endpoint using your custom @app.query decorator
|
|
82
|
+
@app.query("/products/filter", response_model=SearchResponse)
|
|
83
|
+
async def filter_products(
|
|
84
|
+
filters: SearchFilters,
|
|
85
|
+
limit: int = Query(default=10, ge=1),
|
|
86
|
+
order_by: str = "id",
|
|
87
|
+
):
|
|
88
|
+
# Fetch and filter the mock data
|
|
89
|
+
filtered_products = get_products_from_sqlite(
|
|
90
|
+
filters=filters,
|
|
91
|
+
limit=limit,
|
|
92
|
+
order_by=order_by,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
execution_id = str(uuid.uuid4())
|
|
96
|
+
|
|
97
|
+
return JSONResponse(
|
|
98
|
+
content={
|
|
99
|
+
"status": "success",
|
|
100
|
+
"execution_id": execution_id,
|
|
101
|
+
"total_found": len(filtered_products),
|
|
102
|
+
"products": filtered_products,
|
|
103
|
+
},
|
|
104
|
+
headers={
|
|
105
|
+
"X-Execution-Id": execution_id,
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# 6. Direct startup block
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
uvicorn.run(
|
|
113
|
+
"main:app",
|
|
114
|
+
host="127.0.0.1",
|
|
115
|
+
port=8000,
|
|
116
|
+
reload=True,
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Swagger compatibility
|
|
121
|
+
|
|
122
|
+
After starting the application:
|
|
123
|
+
|
|
124
|
+
http://localhost:8000/docs
|
|
125
|
+
|
|
126
|
+
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
127
|
+
|
|
128
|
+
For that reason this package automatically exposes QUERY endpoints as
|
|
129
|
+
both:
|
|
130
|
+
|
|
131
|
+
- QUERY
|
|
132
|
+
- POST
|
|
133
|
+
|
|
134
|
+
Use the **POST** operation in Swagger only for interactive testing.
|
|
135
|
+
|
|
136
|
+
Real clients should invoke the QUERY method directly.
|
|
137
|
+
|
|
138
|
+
<p align="center">
|
|
139
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
140
|
+
</p>
|
|
141
|
+
|
|
142
|
+
## Cache
|
|
143
|
+
|
|
144
|
+
`query_saving_cache=True` allows caching.
|
|
145
|
+
|
|
146
|
+
`query_saving_cache=False` automatically adds:
|
|
147
|
+
|
|
148
|
+
- Cache-Control: no-store
|
|
149
|
+
- Pragma: no-cache
|
|
150
|
+
- Expires: 0
|
|
151
|
+
|
|
152
|
+
## Testing API
|
|
153
|
+
|
|
154
|
+
``` bash
|
|
155
|
+
python validate_data/test_api_query_method.py
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
<p align="center">
|
|
159
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
160
|
+
</p>
|
|
161
|
+
|
|
162
|
+
## Testing Cache
|
|
163
|
+
|
|
164
|
+
### Using Cache Stored
|
|
165
|
+
``` bash
|
|
166
|
+
python validate_data/test_cache_comparison.py
|
|
167
|
+
```
|
|
168
|
+
<p align="center">
|
|
169
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
170
|
+
</p>
|
|
171
|
+
|
|
172
|
+
### NO Using Cache Stored
|
|
173
|
+
<p align="center">
|
|
174
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
175
|
+
</p>
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-extended-query-method
|
|
3
|
+
Version: 0.0.33
|
|
4
|
+
Summary: Native HTTP QUERY method support for FastAPI with automatic cache control and Swagger compatibility.
|
|
5
|
+
Home-page: https://github.com/JorgeCardona/fastapi-extended-query-method
|
|
6
|
+
Author: Jorge Cardona
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: fastapi>=0.139.0
|
|
14
|
+
Requires-Dist: uvicorn>=0.5.1
|
|
15
|
+
Requires-Dist: requests>=2.34.2
|
|
16
|
+
Requires-Dist: requests-cache>=1.3.3
|
|
17
|
+
Requires-Dist: tabulate>=0.10.0
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
Dynamic: requires-dist
|
|
25
|
+
Dynamic: requires-python
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
# FastAPI Extended Query Method
|
|
29
|
+
|
|
30
|
+
Native HTTP QUERY support for FastAPI.
|
|
31
|
+
|
|
32
|
+
## Overview
|
|
33
|
+
|
|
34
|
+
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
35
|
+
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
``` bash
|
|
40
|
+
pip install fastapi-extended-query-method
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
``` python
|
|
46
|
+
import uuid
|
|
47
|
+
from typing import List, Optional
|
|
48
|
+
import uvicorn
|
|
49
|
+
from fastapi import Query
|
|
50
|
+
from fastapi.responses import JSONResponse
|
|
51
|
+
from pydantic import BaseModel
|
|
52
|
+
|
|
53
|
+
# 1. Initialize the app using your custom class
|
|
54
|
+
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
55
|
+
|
|
56
|
+
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
57
|
+
|
|
58
|
+
# 2. Mock Data for quick testing
|
|
59
|
+
MOCK_PRODUCTS = [
|
|
60
|
+
{"id": 1, "name": "Gaming Laptop", "category": "electronics", "price": 1200.99},
|
|
61
|
+
{"id": 2, "name": "Smartphone", "category": "electronics", "price": 599.99},
|
|
62
|
+
{"id": 3, "name": "Bluetooth Headphones", "category": "electronics", "price": 79.90},
|
|
63
|
+
{"id": 4, "name": "Espresso Machine", "category": "appliances", "price": 150.00},
|
|
64
|
+
{"id": 5, "name": "Blender", "category": "appliances", "price": 45.50},
|
|
65
|
+
{"id": 6, "name": "Office Chair", "category": "furniture", "price": 180.00},
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# 3. Pydantic Schemas
|
|
69
|
+
class SearchFilters(BaseModel):
|
|
70
|
+
category: Optional[str] = None
|
|
71
|
+
min_price: Optional[float] = None
|
|
72
|
+
max_price: Optional[float] = None
|
|
73
|
+
|
|
74
|
+
class ProductSchema(BaseModel):
|
|
75
|
+
id: int
|
|
76
|
+
name: str
|
|
77
|
+
category: str
|
|
78
|
+
price: float
|
|
79
|
+
|
|
80
|
+
class SearchResponse(BaseModel):
|
|
81
|
+
status: str
|
|
82
|
+
execution_id: str
|
|
83
|
+
total_found: int
|
|
84
|
+
products: List[ProductSchema]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# 4. Filter function simulating database queries with mock data
|
|
88
|
+
def get_products_from_sqlite(filters: SearchFilters, limit: int, order_by: str):
|
|
89
|
+
results = MOCK_PRODUCTS.copy()
|
|
90
|
+
|
|
91
|
+
# Apply search filters if they are provided
|
|
92
|
+
if filters.category:
|
|
93
|
+
results = [p for p in results if p["category"].lower() == filters.category.lower()]
|
|
94
|
+
|
|
95
|
+
if filters.min_price is not None:
|
|
96
|
+
results = [p for p in results if p["price"] >= filters.min_price]
|
|
97
|
+
|
|
98
|
+
if filters.max_price is not None:
|
|
99
|
+
results = [p for p in results if p["price"] <= filters.max_price]
|
|
100
|
+
|
|
101
|
+
# Sort results dynamically (defaults to "id")
|
|
102
|
+
results = sorted(results, key=lambda x: x.get(order_by, x["id"]))
|
|
103
|
+
|
|
104
|
+
# Apply limit
|
|
105
|
+
return results[:limit]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# 5. Endpoint using your custom @app.query decorator
|
|
109
|
+
@app.query("/products/filter", response_model=SearchResponse)
|
|
110
|
+
async def filter_products(
|
|
111
|
+
filters: SearchFilters,
|
|
112
|
+
limit: int = Query(default=10, ge=1),
|
|
113
|
+
order_by: str = "id",
|
|
114
|
+
):
|
|
115
|
+
# Fetch and filter the mock data
|
|
116
|
+
filtered_products = get_products_from_sqlite(
|
|
117
|
+
filters=filters,
|
|
118
|
+
limit=limit,
|
|
119
|
+
order_by=order_by,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
execution_id = str(uuid.uuid4())
|
|
123
|
+
|
|
124
|
+
return JSONResponse(
|
|
125
|
+
content={
|
|
126
|
+
"status": "success",
|
|
127
|
+
"execution_id": execution_id,
|
|
128
|
+
"total_found": len(filtered_products),
|
|
129
|
+
"products": filtered_products,
|
|
130
|
+
},
|
|
131
|
+
headers={
|
|
132
|
+
"X-Execution-Id": execution_id,
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# 6. Direct startup block
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
uvicorn.run(
|
|
140
|
+
"main:app",
|
|
141
|
+
host="127.0.0.1",
|
|
142
|
+
port=8000,
|
|
143
|
+
reload=True,
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Swagger compatibility
|
|
148
|
+
|
|
149
|
+
After starting the application:
|
|
150
|
+
|
|
151
|
+
http://localhost:8000/docs
|
|
152
|
+
|
|
153
|
+
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
154
|
+
|
|
155
|
+
For that reason this package automatically exposes QUERY endpoints as
|
|
156
|
+
both:
|
|
157
|
+
|
|
158
|
+
- QUERY
|
|
159
|
+
- POST
|
|
160
|
+
|
|
161
|
+
Use the **POST** operation in Swagger only for interactive testing.
|
|
162
|
+
|
|
163
|
+
Real clients should invoke the QUERY method directly.
|
|
164
|
+
|
|
165
|
+
<p align="center">
|
|
166
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
167
|
+
</p>
|
|
168
|
+
|
|
169
|
+
## Cache
|
|
170
|
+
|
|
171
|
+
`query_saving_cache=True` allows caching.
|
|
172
|
+
|
|
173
|
+
`query_saving_cache=False` automatically adds:
|
|
174
|
+
|
|
175
|
+
- Cache-Control: no-store
|
|
176
|
+
- Pragma: no-cache
|
|
177
|
+
- Expires: 0
|
|
178
|
+
|
|
179
|
+
## Testing API
|
|
180
|
+
|
|
181
|
+
``` bash
|
|
182
|
+
python validate_data/test_api_query_method.py
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
<p align="center">
|
|
186
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
187
|
+
</p>
|
|
188
|
+
|
|
189
|
+
## Testing Cache
|
|
190
|
+
|
|
191
|
+
### Using Cache Stored
|
|
192
|
+
``` bash
|
|
193
|
+
python validate_data/test_cache_comparison.py
|
|
194
|
+
```
|
|
195
|
+
<p align="center">
|
|
196
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
197
|
+
</p>
|
|
198
|
+
|
|
199
|
+
### NO Using Cache Stored
|
|
200
|
+
<p align="center">
|
|
201
|
+
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
202
|
+
</p>
|
|
203
|
+
|
|
204
|
+
## License
|
|
205
|
+
|
|
206
|
+
MIT
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: fastapi-extended-query-method
|
|
3
|
-
Version: 0.0.32
|
|
4
|
-
Summary: Native HTTP QUERY method support for FastAPI with automatic cache control and Swagger compatibility.
|
|
5
|
-
Home-page: https://github.com/JorgeCardona/fastapi-extended-query-method
|
|
6
|
-
Author: Jorge Cardona
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Requires-Python: >=3.10
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Requires-Dist: fastapi>=0.139.0
|
|
14
|
-
Requires-Dist: uvicorn>=0.5.1
|
|
15
|
-
Requires-Dist: requests>=2.34.2
|
|
16
|
-
Requires-Dist: requests-cache>=1.3.3
|
|
17
|
-
Requires-Dist: tabulate>=0.10.0
|
|
18
|
-
Dynamic: author
|
|
19
|
-
Dynamic: classifier
|
|
20
|
-
Dynamic: description
|
|
21
|
-
Dynamic: description-content-type
|
|
22
|
-
Dynamic: home-page
|
|
23
|
-
Dynamic: license-file
|
|
24
|
-
Dynamic: requires-dist
|
|
25
|
-
Dynamic: requires-python
|
|
26
|
-
Dynamic: summary
|
|
27
|
-
|
|
28
|
-
# FastAPI Extended Query Method
|
|
29
|
-
|
|
30
|
-
Native HTTP QUERY support for FastAPI.
|
|
31
|
-
|
|
32
|
-
## Overview
|
|
33
|
-
|
|
34
|
-
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
35
|
-
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
36
|
-
|
|
37
|
-
## Installation
|
|
38
|
-
|
|
39
|
-
``` bash
|
|
40
|
-
pip install fastapi-extended-query-method
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Quick Start
|
|
44
|
-
|
|
45
|
-
``` python
|
|
46
|
-
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
47
|
-
|
|
48
|
-
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Swagger compatibility
|
|
52
|
-
|
|
53
|
-
After starting the application:
|
|
54
|
-
|
|
55
|
-
http://localhost:8000/docs
|
|
56
|
-
|
|
57
|
-
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
58
|
-
|
|
59
|
-
For that reason this package automatically exposes QUERY endpoints as
|
|
60
|
-
both:
|
|
61
|
-
|
|
62
|
-
- QUERY
|
|
63
|
-
- POST
|
|
64
|
-
|
|
65
|
-
Use the **POST** operation in Swagger only for interactive testing.
|
|
66
|
-
|
|
67
|
-
Real clients should invoke the QUERY method directly.
|
|
68
|
-
|
|
69
|
-
<p align="center">
|
|
70
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
## Cache
|
|
74
|
-
|
|
75
|
-
`query_saving_cache=True` allows caching.
|
|
76
|
-
|
|
77
|
-
`query_saving_cache=False` automatically adds:
|
|
78
|
-
|
|
79
|
-
- Cache-Control: no-store
|
|
80
|
-
- Pragma: no-cache
|
|
81
|
-
- Expires: 0
|
|
82
|
-
|
|
83
|
-
## Testing API
|
|
84
|
-
|
|
85
|
-
``` bash
|
|
86
|
-
python validate_data/test_api_query_method.py
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
<p align="center">
|
|
90
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
91
|
-
</p>
|
|
92
|
-
|
|
93
|
-
## Testing Cache
|
|
94
|
-
|
|
95
|
-
### Using Cache Stored
|
|
96
|
-
``` bash
|
|
97
|
-
python validate_data/test_cache_comparison.py
|
|
98
|
-
```
|
|
99
|
-
<p align="center">
|
|
100
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
101
|
-
</p>
|
|
102
|
-
|
|
103
|
-
### NO Using Cache Stored
|
|
104
|
-
<p align="center">
|
|
105
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
106
|
-
</p>
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
MIT
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# FastAPI Extended Query Method
|
|
2
|
-
|
|
3
|
-
Native HTTP QUERY support for FastAPI.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
8
|
-
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
9
|
-
|
|
10
|
-
## Installation
|
|
11
|
-
|
|
12
|
-
``` bash
|
|
13
|
-
pip install fastapi-extended-query-method
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Quick Start
|
|
17
|
-
|
|
18
|
-
``` python
|
|
19
|
-
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
20
|
-
|
|
21
|
-
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Swagger compatibility
|
|
25
|
-
|
|
26
|
-
After starting the application:
|
|
27
|
-
|
|
28
|
-
http://localhost:8000/docs
|
|
29
|
-
|
|
30
|
-
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
31
|
-
|
|
32
|
-
For that reason this package automatically exposes QUERY endpoints as
|
|
33
|
-
both:
|
|
34
|
-
|
|
35
|
-
- QUERY
|
|
36
|
-
- POST
|
|
37
|
-
|
|
38
|
-
Use the **POST** operation in Swagger only for interactive testing.
|
|
39
|
-
|
|
40
|
-
Real clients should invoke the QUERY method directly.
|
|
41
|
-
|
|
42
|
-
<p align="center">
|
|
43
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
44
|
-
</p>
|
|
45
|
-
|
|
46
|
-
## Cache
|
|
47
|
-
|
|
48
|
-
`query_saving_cache=True` allows caching.
|
|
49
|
-
|
|
50
|
-
`query_saving_cache=False` automatically adds:
|
|
51
|
-
|
|
52
|
-
- Cache-Control: no-store
|
|
53
|
-
- Pragma: no-cache
|
|
54
|
-
- Expires: 0
|
|
55
|
-
|
|
56
|
-
## Testing API
|
|
57
|
-
|
|
58
|
-
``` bash
|
|
59
|
-
python validate_data/test_api_query_method.py
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
<p align="center">
|
|
63
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
64
|
-
</p>
|
|
65
|
-
|
|
66
|
-
## Testing Cache
|
|
67
|
-
|
|
68
|
-
### Using Cache Stored
|
|
69
|
-
``` bash
|
|
70
|
-
python validate_data/test_cache_comparison.py
|
|
71
|
-
```
|
|
72
|
-
<p align="center">
|
|
73
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
74
|
-
</p>
|
|
75
|
-
|
|
76
|
-
### NO Using Cache Stored
|
|
77
|
-
<p align="center">
|
|
78
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
79
|
-
</p>
|
|
80
|
-
|
|
81
|
-
## License
|
|
82
|
-
|
|
83
|
-
MIT
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: fastapi-extended-query-method
|
|
3
|
-
Version: 0.0.32
|
|
4
|
-
Summary: Native HTTP QUERY method support for FastAPI with automatic cache control and Swagger compatibility.
|
|
5
|
-
Home-page: https://github.com/JorgeCardona/fastapi-extended-query-method
|
|
6
|
-
Author: Jorge Cardona
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
-
Classifier: Operating System :: OS Independent
|
|
10
|
-
Requires-Python: >=3.10
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
Requires-Dist: fastapi>=0.139.0
|
|
14
|
-
Requires-Dist: uvicorn>=0.5.1
|
|
15
|
-
Requires-Dist: requests>=2.34.2
|
|
16
|
-
Requires-Dist: requests-cache>=1.3.3
|
|
17
|
-
Requires-Dist: tabulate>=0.10.0
|
|
18
|
-
Dynamic: author
|
|
19
|
-
Dynamic: classifier
|
|
20
|
-
Dynamic: description
|
|
21
|
-
Dynamic: description-content-type
|
|
22
|
-
Dynamic: home-page
|
|
23
|
-
Dynamic: license-file
|
|
24
|
-
Dynamic: requires-dist
|
|
25
|
-
Dynamic: requires-python
|
|
26
|
-
Dynamic: summary
|
|
27
|
-
|
|
28
|
-
# FastAPI Extended Query Method
|
|
29
|
-
|
|
30
|
-
Native HTTP QUERY support for FastAPI.
|
|
31
|
-
|
|
32
|
-
## Overview
|
|
33
|
-
|
|
34
|
-
`FastAPIWithQueryHttpMethod` extends FastAPI with native support for the
|
|
35
|
-
HTTP QUERY method while preserving the FastAPI developer experience.
|
|
36
|
-
|
|
37
|
-
## Installation
|
|
38
|
-
|
|
39
|
-
``` bash
|
|
40
|
-
pip install fastapi-extended-query-method
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Quick Start
|
|
44
|
-
|
|
45
|
-
``` python
|
|
46
|
-
from fastapi_extended_query_method import FastAPIWithQueryHttpMethod
|
|
47
|
-
|
|
48
|
-
app = FastAPIWithQueryHttpMethod(query_saving_cache=True)
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Swagger compatibility
|
|
52
|
-
|
|
53
|
-
After starting the application:
|
|
54
|
-
|
|
55
|
-
http://localhost:8000/docs
|
|
56
|
-
|
|
57
|
-
OpenAPI and Swagger do **not** currently support the HTTP QUERY method.
|
|
58
|
-
|
|
59
|
-
For that reason this package automatically exposes QUERY endpoints as
|
|
60
|
-
both:
|
|
61
|
-
|
|
62
|
-
- QUERY
|
|
63
|
-
- POST
|
|
64
|
-
|
|
65
|
-
Use the **POST** operation in Swagger only for interactive testing.
|
|
66
|
-
|
|
67
|
-
Real clients should invoke the QUERY method directly.
|
|
68
|
-
|
|
69
|
-
<p align="center">
|
|
70
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/swagger.png" alt="Swagger Interface" width="900">
|
|
71
|
-
</p>
|
|
72
|
-
|
|
73
|
-
## Cache
|
|
74
|
-
|
|
75
|
-
`query_saving_cache=True` allows caching.
|
|
76
|
-
|
|
77
|
-
`query_saving_cache=False` automatically adds:
|
|
78
|
-
|
|
79
|
-
- Cache-Control: no-store
|
|
80
|
-
- Pragma: no-cache
|
|
81
|
-
- Expires: 0
|
|
82
|
-
|
|
83
|
-
## Testing API
|
|
84
|
-
|
|
85
|
-
``` bash
|
|
86
|
-
python validate_data/test_api_query_method.py
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
<p align="center">
|
|
90
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/api_results.png" alt="API Results" width="900">
|
|
91
|
-
</p>
|
|
92
|
-
|
|
93
|
-
## Testing Cache
|
|
94
|
-
|
|
95
|
-
### Using Cache Stored
|
|
96
|
-
``` bash
|
|
97
|
-
python validate_data/test_cache_comparison.py
|
|
98
|
-
```
|
|
99
|
-
<p align="center">
|
|
100
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/cache.png" alt="Stored Cache" width="900">
|
|
101
|
-
</p>
|
|
102
|
-
|
|
103
|
-
### NO Using Cache Stored
|
|
104
|
-
<p align="center">
|
|
105
|
-
<img src="https://raw.githubusercontent.com/JorgeCardona/fastapi-extended-query-method/refs/heads/main/images/no_cache.png" alt="Without Cache" width="900">
|
|
106
|
-
</p>
|
|
107
|
-
|
|
108
|
-
## License
|
|
109
|
-
|
|
110
|
-
MIT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|