Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom URL method router for CRUD APIView #1344

Open
stiangrim opened this issue Dec 6, 2024 · 0 comments
Open

Custom URL method router for CRUD APIView #1344

stiangrim opened this issue Dec 6, 2024 · 0 comments

Comments

@stiangrim
Copy link

Hi 👋
I tried searching, but I'll apologize in advance if this has been asked before.

I've tried splitting up every CRUD operation of a model into separate APIView's, as inspiration from the Django Styleguide.

However, in order to do this, you need some sort of method router to link the URL's to each API correctly. The method router I've built does however not work with drf-spectacular, as the endpoints does not show up in the generated docs.

I've opened up an issue in the styleguide repo as well, but figured that this was a more fitting place.

I'll post my current code for routing the different methods, which works for everything except drf-spectacular docs:

from typing import Any

from django.http.response import HttpResponseBase
from rest_framework.request import Request
from rest_framework.views import APIView


class MethodDispatcherView(APIView):
    """
    A reusable dispatcher view that routes requests to different API views
    based on the HTTP method.
    """

    def __init__(self, method_views: dict, **kwargs: dict) -> None:
        super().__init__(**kwargs)
        self.method_views = method_views

    def dispatch(
        self, request: Request, *args: list, **kwargs: dict
    ) -> HttpResponseBase:
        """
        Override the dispatch method to route requests to specific views based
        on the HTTP method (GET, POST, etc.)
        """
        view = self.method_views.get(request.method)
        if view:
            return view.as_view()(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)


def build_method_router(method_views: Any) -> Any:
    """
    Factory function to create an instance of MethodDispatcherView with
    specified method_views.
    """

    class CustomMethodDispatcherView(MethodDispatcherView):
        def __init__(self, **kwargs: dict) -> None:
            super().__init__(method_views=method_views, **kwargs)

    return CustomMethodDispatcherView.as_view()

Example usage:

urlpatterns = [
    path(
        "users/",
        build_method_router({"GET": UserListApi, "POST": UserCreateApi}),
        name="users",
    ),
    path(
        "users/<int:user_id>",
        build_method_router(
            {
                "GET": UserGetApi,
                "PATCH": UserUpdateApi,
            }
        ),
        name="user",
    )
]

Can anyone guide me in a direction in how to get the docs up and running? 🙏

@stiangrim stiangrim changed the title CRUD APIView's Custom URL method router for CRUD APIView Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant