Skip to content

Instantly share code, notes, and snippets.

@denizdogan
Created September 22, 2022 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save denizdogan/5fb268a2848e1da25f23ea9f25eaefc5 to your computer and use it in GitHub Desktop.
Save denizdogan/5fb268a2848e1da25f23ea9f25eaefc5 to your computer and use it in GitHub Desktop.
Never write Django again
# i wrote this as a joke, don't worry
# ...but it actually works
from django.db.models import QuerySet
from django.shortcuts import get_object_or_404
from ninja import Router, Schema
from pydantic.typing import Dict, Union, Literal, Optional, Type
from myproject.people.models import Person
CRUD_IN_METHOD = Literal["GET", "POST", "PATCH", "DELETE"]
CRUD_PATHS = {"GET": "{id}", "POST": "", "PATCH": "{id}", "DELETE": "{id}"}
CRUD_SCHEMA_MAPPING = Dict[CRUD_IN_METHOD, Union[Type[Schema], Dict[int, Type[Schema]]]]
def crud_me_up_scotty(
router,
queryset: QuerySet,
requests: CRUD_SCHEMA_MAPPING,
responses: CRUD_SCHEMA_MAPPING,
):
model = queryset.model
def make_view(
method: str,
request_schema: Optional[Type[Schema]],
response_schemas: Dict[int, Type[Schema]],
):
path = CRUD_PATHS[method]
if method == "GET":
def get(request, id: str, *args, **kwargs):
f"""retrieve a {model}"""
print(f"{request.user} is requesting {model} with id {id}")
instance = get_object_or_404(queryset, id=id)
return 200, instance
router.add_api_operation(path, [method], get, response=response_schemas)
return get
if method == "POST":
def post(request, payload: request_schema, *args, **kwargs):
f"""create a {model}"""
print(f"{request.user} is creating a {model}")
instance = queryset.create(**dict(payload))
return 201, instance
router.add_api_operation(path, [method], post, response=response_schemas)
return post
# ...TODO...
crud_views = {
method: make_view(method, requests.get(method, None), responses.get(method, {}))
for method in {*requests.keys(), *responses.keys()}
}
return crud_views
class GetPersonOut(Schema):
id: str
first_name: str
last_name: str
birthyear: int
class PostPersonOut(Schema):
id: str
first_name: str
last_name: str
birthyear: int
class PostPersonIn(Schema):
first_name: str
last_name: str
birthyear: int
people_router = Router(tags=["people"])
crud_views = crud_me_up_scotty(
people_router,
Person.objects.all(),
requests={"POST": PostPersonIn},
responses={"GET": {200: GetPersonOut}, "POST": {201: PostPersonOut}},
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment