Browse Source

Merge remote changes and fix import sorting

- Resolve merge conflicts from remote updates
- Maintain import organization fixes
- Update documentation examples
pull/13948/head
yogishhg9964 4 days ago
parent
commit
b0c4d5021e
  1. 8
      docs_src/query_method/query_method_001.py
  2. 82
      docs_src/query_method/query_method_002.py
  3. 71
      docs_src/query_method/query_method_003.py

8
docs_src/query_method/query_method_001.py

@ -6,9 +6,10 @@ Example: Basic QUERY method usage in FastAPI.
This example demonstrates how to use the QUERY HTTP method for simple queries.
"""
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
@ -28,13 +29,12 @@ def search_items(query: SimpleQuery):
"""
# Simulate search logic
results = [
f"Item {i}: {query.search_term}"
for i in range(1, min(query.limit + 1, 6))
f"Item {i}: {query.search_term}" for i in range(1, min(query.limit + 1, 6))
]
return {
"query": query.search_term,
"limit": query.limit,
"results": results,
"total_found": len(results)
"total_found": len(results),
}

82
docs_src/query_method/query_method_002.py

@ -7,9 +7,10 @@ This example demonstrates the power of the QUERY method for complex data filteri
and field selection, similar to GraphQL but using standard HTTP.
"""
from typing import Any, Dict, List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
app = FastAPI()
@ -24,7 +25,7 @@ sample_data = [
"id": 101,
"name": "Dr. Smith",
"email": "smith@university.edu",
"bio": "Mathematics professor with 20 years experience"
"bio": "Mathematics professor with 20 years experience",
},
"topics": [
{
@ -34,8 +35,8 @@ sample_data = [
"lessons": 15,
"exercises": [
{"id": 1, "title": "Linear Equations", "points": 10},
{"id": 2, "title": "Quadratic Equations", "points": 15}
]
{"id": 2, "title": "Quadratic Equations", "points": 15},
],
},
{
"id": 2,
@ -44,13 +45,13 @@ sample_data = [
"lessons": 20,
"exercises": [
{"id": 3, "title": "Derivatives", "points": 20},
{"id": 4, "title": "Integrals", "points": 25}
]
}
{"id": 4, "title": "Integrals", "points": 25},
],
},
],
"tags": ["mathematics", "algebra", "calculus"],
"rating": 4.8,
"enrolled_students": 245
"enrolled_students": 245,
},
{
"id": 2,
@ -60,7 +61,7 @@ sample_data = [
"id": 102,
"name": "Dr. Johnson",
"email": "johnson@university.edu",
"bio": "Physics professor specializing in quantum mechanics"
"bio": "Physics professor specializing in quantum mechanics",
},
"topics": [
{
@ -70,19 +71,20 @@ sample_data = [
"lessons": 25,
"exercises": [
{"id": 5, "title": "Wave Functions", "points": 30},
{"id": 6, "title": "Uncertainty Principle", "points": 35}
]
{"id": 6, "title": "Uncertainty Principle", "points": 35},
],
}
],
"tags": ["physics", "quantum", "mechanics"],
"rating": 4.9,
"enrolled_students": 156
}
"enrolled_students": 156,
},
]
class FieldSelector(BaseModel):
"""Define which fields to include in the response."""
course_fields: Optional[List[str]] = None
instructor_fields: Optional[List[str]] = None
topic_fields: Optional[List[str]] = None
@ -91,6 +93,7 @@ class FieldSelector(BaseModel):
class QueryFilter(BaseModel):
"""Define filters for the query."""
min_rating: Optional[float] = None
max_rating: Optional[float] = None
difficulty: Optional[str] = None
@ -100,13 +103,16 @@ class QueryFilter(BaseModel):
class CourseQuery(BaseModel):
"""Complete query schema for course data."""
fields: Optional[FieldSelector] = None
filters: Optional[QueryFilter] = None
limit: Optional[int] = 10
offset: Optional[int] = 0
def filter_object(obj: Dict[str, Any], allowed_fields: Optional[List[str]] = None) -> Dict[str, Any]:
def filter_object(
obj: Dict[str, Any], allowed_fields: Optional[List[str]] = None
) -> Dict[str, Any]:
"""Filter an object to only include specified fields."""
if allowed_fields is None:
return obj
@ -121,33 +127,50 @@ def apply_filters(data: List[Dict], filters: Optional[QueryFilter]) -> List[Dict
filtered_data = data.copy()
if filters.min_rating is not None:
filtered_data = [item for item in filtered_data if item.get("rating", 0) >= filters.min_rating]
filtered_data = [
item
for item in filtered_data
if item.get("rating", 0) >= filters.min_rating
]
if filters.max_rating is not None:
filtered_data = [item for item in filtered_data if item.get("rating", 0) <= filters.max_rating]
filtered_data = [
item
for item in filtered_data
if item.get("rating", 0) <= filters.max_rating
]
if filters.difficulty:
filtered_data = [
item for item in filtered_data
if any(topic.get("difficulty") == filters.difficulty for topic in item.get("topics", []))
item
for item in filtered_data
if any(
topic.get("difficulty") == filters.difficulty
for topic in item.get("topics", [])
)
]
if filters.tags:
filtered_data = [
item for item in filtered_data
item
for item in filtered_data
if any(tag in item.get("tags", []) for tag in filters.tags)
]
if filters.instructor_name:
filtered_data = [
item for item in filtered_data
if filters.instructor_name.lower() in item.get("instructor", {}).get("name", "").lower()
item
for item in filtered_data
if filters.instructor_name.lower()
in item.get("instructor", {}).get("name", "").lower()
]
return filtered_data
def apply_field_selection(data: List[Dict], fields: Optional[FieldSelector]) -> List[Dict]:
def apply_field_selection(
data: List[Dict], fields: Optional[FieldSelector]
) -> List[Dict]:
"""Apply field selection to shape the response."""
if not fields:
return data
@ -158,7 +181,9 @@ def apply_field_selection(data: List[Dict], fields: Optional[FieldSelector]) ->
# Filter instructor fields
if "instructor" in item and fields.instructor_fields:
filtered_item["instructor"] = filter_object(item["instructor"], fields.instructor_fields)
filtered_item["instructor"] = filter_object(
item["instructor"], fields.instructor_fields
)
# Filter topic fields
if "topics" in item and fields.topic_fields:
@ -229,7 +254,7 @@ def query_courses(query: CourseQuery):
"returned_results": len(paginated_data),
"offset": offset,
"limit": limit,
"data": paginated_data
"data": paginated_data,
}
@ -245,12 +270,9 @@ def read_root():
"fields": {
"course_fields": ["id", "name", "rating"],
"instructor_fields": ["name"],
"topic_fields": ["title", "difficulty"]
"topic_fields": ["title", "difficulty"],
},
"filters": {
"min_rating": 4.5,
"tags": ["mathematics"]
"filters": {"min_rating": 4.5, "tags": ["mathematics"]},
"limit": 5,
},
"limit": 5
}
}

71
docs_src/query_method/query_method_003.py

@ -10,9 +10,10 @@ This example directly addresses the use case described in the GitHub issue:
- Provides GraphQL-like flexibility with standard HTTP
"""
from typing import Any, Dict, List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
app = FastAPI()
@ -69,13 +70,13 @@ sample_subject = {
"number_of_clicks": 1,
"number_of_votes": 1,
}
]
],
}
]
],
}
]
],
}
]
],
}
@ -84,12 +85,15 @@ class ArbitrarySchema(BaseModel):
The schema that clients send to specify exactly what they want in the response.
This is the key innovation - clients can request any combination of fields.
"""
# Root level fields to include
root_fields: Optional[List[str]] = None
# Nested object field specifications
tags: Optional[Dict[str, Any]] = None # {"fields": ["id", "name"], "limit": 5}
topics: Optional[Dict[str, Any]] = None # {"fields": [...], "limit": 10, "posts": {...}}
topics: Optional[Dict[str, Any]] = (
None # {"fields": [...], "limit": 10, "posts": {...}}
)
# Global limits
max_depth: Optional[int] = None
@ -123,7 +127,11 @@ def filter_by_schema(data: Dict[str, Any], schema: ArbitrarySchema) -> Dict[str,
# Filter fields if specified
if "fields" in tags_config:
tags_data = [
{field: tag.get(field) for field in tags_config["fields"] if field in tag}
{
field: tag.get(field)
for field in tags_config["fields"]
if field in tag
}
for tag in tags_data
]
@ -149,7 +157,9 @@ def filter_by_schema(data: Dict[str, Any], schema: ArbitrarySchema) -> Dict[str,
processed_topic[field] = topic[field]
else:
# Default topic fields
processed_topic = {k: v for k, v in topic.items() if k in ["id", "name"]}
processed_topic = {
k: v for k, v in topic.items() if k in ["id", "name"]
}
# Handle posts within topics
if "posts" in topics_config and "posts" in topic:
@ -169,7 +179,9 @@ def filter_by_schema(data: Dict[str, Any], schema: ArbitrarySchema) -> Dict[str,
if field in post:
processed_post[field] = post[field]
else:
processed_post = {k: v for k, v in post.items() if k in ["id", "title"]}
processed_post = {
k: v for k, v in post.items() if k in ["id", "title"]
}
# Handle answers within posts
if "answers" in posts_config and "answers" in post:
@ -188,7 +200,11 @@ def filter_by_schema(data: Dict[str, Any], schema: ArbitrarySchema) -> Dict[str,
if field in answer:
processed_answer[field] = answer[field]
else:
processed_answer = {k: v for k, v in answer.items() if k in ["id", "content"]}
processed_answer = {
k: v
for k, v in answer.items()
if k in ["id", "content"]
}
# Handle comments within answers
if "comments" in answers_config and "comments" in answer:
@ -196,16 +212,26 @@ def filter_by_schema(data: Dict[str, Any], schema: ArbitrarySchema) -> Dict[str,
comments_data = answer["comments"]
if "limit" in comments_config:
comments_data = comments_data[:comments_config["limit"]]
comments_data = comments_data[
: comments_config["limit"]
]
if "fields" in comments_config:
processed_answer["comments"] = [
{field: comment.get(field) for field in comments_config["fields"] if field in comment}
{
field: comment.get(field)
for field in comments_config["fields"]
if field in comment
}
for comment in comments_data
]
else:
processed_answer["comments"] = [
{k: v for k, v in comment.items() if k in ["id", "content"]}
{
k: v
for k, v in comment.items()
if k in ["id", "content"]
}
for comment in comments_data
]
@ -279,7 +305,7 @@ def query_subjects(schema: ArbitrarySchema):
return {
"message": "Successfully queried subjects using arbitrary schema",
"schema_used": schema.model_dump(),
"data": filtered_data
"data": filtered_data,
}
@ -295,12 +321,12 @@ def get_root():
"usage": {
"endpoint": "/query/subjects",
"method": "QUERY",
"description": "Send arbitrary schema in request body to get exactly the data you need"
"description": "Send arbitrary schema in request body to get exactly the data you need",
},
"examples": {
"minimal": {
"root_fields": ["id", "name"],
"tags": {"fields": ["id", "name"], "limit": 1}
"tags": {"fields": ["id", "name"], "limit": 1},
},
"detailed": {
"root_fields": ["id", "name"],
@ -308,14 +334,11 @@ def get_root():
"fields": ["id", "name"],
"posts": {
"fields": ["id", "title"],
"answers": {
"fields": ["id", "content"],
"limit": 1
}
}
}
}
}
"answers": {"fields": ["id", "content"], "limit": 1},
},
},
},
},
}

Loading…
Cancel
Save