Skip to content

Commit

Permalink
Merge pull request #214 from eadwinCode/controller_route_order
Browse files Browse the repository at this point in the history
fix: Controller Operation Order
  • Loading branch information
eadwinCode authored Dec 5, 2024
2 parents 58c5fe3 + 050004e commit 879ff04
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 5 deletions.
2 changes: 1 addition & 1 deletion ninja_extra/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Django Ninja Extra - Class Based Utility and more for Django Ninja(Fast Django REST framework)"""

__version__ = "0.21.7"
__version__ = "0.21.8"

import django

Expand Down
22 changes: 19 additions & 3 deletions ninja_extra/controllers/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import inspect
import re
import uuid
from abc import ABC
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -62,9 +63,24 @@ class MissingAPIControllerDecoratorException(Exception):


def get_route_functions(cls: Type) -> Iterable[RouteFunction]:
for _, method in inspect.getmembers(cls, predicate=inspect.isfunction):
if hasattr(method, ROUTE_FUNCTION):
yield getattr(method, ROUTE_FUNCTION)
"""
Get all route functions from a controller class.
This function will recursively search for route functions in the base classes of the controller class
in order that they are defined.
Args:
cls (Type): The controller class.
Returns:
Iterable[RouteFunction]: An iterable of route functions.
"""

bases = inspect.getmro(cls)
for base_cls in reversed(bases):
if base_cls not in [ControllerBase, ABC, object]:
for method in base_cls.__dict__.values():
if hasattr(method, ROUTE_FUNCTION):
yield getattr(method, ROUTE_FUNCTION)


def get_all_controller_route_function(
Expand Down
30 changes: 29 additions & 1 deletion tests/test_operation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import uuid

import django
import pytest

from ninja_extra import api_controller, route
from ninja_extra import api_controller, http_delete, http_get, route, status
from ninja_extra.controllers import AsyncRouteFunction, RouteFunction
from ninja_extra.helper import get_route_function
from ninja_extra.operation import AsyncOperation, Operation
Expand Down Expand Up @@ -113,3 +115,29 @@ async def test_async_route_operation_execution_should_log_execution(self):
client = TestAsyncClient(self.SomeTestController)
with pytest.raises(CustomException):
await client.get("/example_exception")


def test_controller_operation_order():
@api_controller("/my/api/users", tags=["User"])
class UserAPIController:
@http_get("/me")
def get_current_user(self, request):
return {"debug": "ok", "message": "Current user"}

@http_get("/{user_id}")
def get_user(self, request, user_id: uuid.UUID):
return {"debug": "ok", "message": "User"}

@http_delete("/{user_id}", response={status.HTTP_204_NO_CONTENT: None})
def delete_user_from_clinic(self, request, user_id: uuid.UUID):
return {"debug": "ok", "message": "User deleted"}

client = TestClient(UserAPIController)
response = client.get("/me")
assert response.json() == {"debug": "ok", "message": "Current user"}

response = client.get(f"/{uuid.uuid4()}")
assert response.json() == {"debug": "ok", "message": "User"}

response = client.delete(f"/{uuid.uuid4()}")
assert response.content == b""

0 comments on commit 879ff04

Please sign in to comment.