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

How to put Controller under router #128

Open
pirate opened this issue Apr 25, 2024 · 3 comments
Open

How to put Controller under router #128

pirate opened this issue Apr 25, 2024 · 3 comments

Comments

@pirate
Copy link

pirate commented Apr 25, 2024

I'm wondering how I register a controller to a router, this doesn't seem to work:

# trying to register a controller on a router doesnt work:
router.register_controllers(EventModelController)

# trying to nest under an existing router also doesn't work:
router.add_router('event',            EventModelController)

I have the following simplified setup:

api/urls.py:

api = NinjaExtraAPI(auth=django_auth)

api.add_router('/auth/',     'api.routes_auth.router')
api.add_router('/models/',   'api.routes_models.router')

urlpatterns = [
    path("v1/",              api.urls),
    path("v1",               RedirectView.as_view(url='/api/v1/docs')),
    path("",                 RedirectView.as_view(url='/api/v1/docs')),
]

api/routes_auth.py:

router = Router(tags=['Authentication'])

@router.post("/get_token", auth=None, summary='Get an API token for a given user & pass')
def get_token(request, auth_data: PasswordAuthSchema):
	...
	
@router.post("/validate_token", auth=None, summary='Validate a given API token')
def validate_token(request, token_data: TokenAuthSchema):
    ...

api/routes_models.py:

from core.models import Event

...

router = Router(tags=['Core Data Models'])

@api_controller()
class EventModelController(ModelControllerBase):
    model_config = ModelConfig(
        model=Event,
        schema_config=ModelSchemaConfig(read_only_fields=["id"]),
    )

# this fails however:
router.add_router('event',            EventModelController)

So my question is, how does one properly nest a controller under an existing router? (without direct access to the top-level api object)

@eadwinCode
Copy link
Owner

@pirate Controllers can not be registered to routers because it does not follow a full Ninja router interface.

Also, controllers do not support nesting with routers or other controllers.

But if you want to lazy load the controllers, you can do the following for now:

from django.utils.module_loading import import_string
...

api = NinjaExtraAPI(auth=django_auth)
api.register_controllers(
    import_string('api.routes_models.EventModelController'), 
)

api.add_router('/auth/',     'api.routes_auth.router')
api.add_router('/models/',   'api.routes_models.router')

urlpatterns = [
    path("v1/",              api.urls),
    path("v1",               RedirectView.as_view(url='/api/v1/docs')),
    path("",                 RedirectView.as_view(url='/api/v1/docs')),
]

I will work on a better lazy loading setup for controllers.

@pirate
Copy link
Author

pirate commented Apr 25, 2024

The issue is I need the controller to live below a router because I'm mixing-and-matching a bunch of normal Django-ninja router routes next to the controller at the same level.

E.g.

  • /api/models = Django-ninja router
  • /api/models/Event -> EventController (ninja-extra)
  • /api/models/Foo/search -> Django-ninja router
  • /api/models/Bar -> Django-ninja router

(The context is I'm using Django-extra not for the class based routes, but just for the automatic ModelController on models I'm too lazy to implement myself. I do my own function based CRUD interfaces on the important ones, but for less important ones I was hoping to get CRUD interfaces for free)

@eadwinCode
Copy link
Owner

You can still use your event controller without mixing it with a router. If I am to implement this, with your route paths setup, I would do the following:
api/urls.py:

api = NinjaExtraAPI(auth=django_auth)
api.register_controllers(
    import_string('api.routes_models.EventModelController'), 
)

api.add_router('/auth/',     'api.routes_auth.router')
api.add_router('/models/',   'api.routes_models.router')


urlpatterns = [
    path("v1/",              api.urls),
    path("v1",               RedirectView.as_view(url='/api/v1/docs')),
    path("",                 RedirectView.as_view(url='/api/v1/docs')),
]

api/routes_auth.py:

router = Router(tags=['Authentication'])

@router.post("/get_token", auth=None, summary='Get an API token for a given user & pass')
def get_token(request, auth_data: PasswordAuthSchema):
	...
	
@router.post("/validate_token", auth=None, summary='Validate a given API token')
def validate_token(request, token_data: TokenAuthSchema):
    ...

api/routes_models.py:

from core.models import Event

...
# specifies the path as a prefix to controller routes. just as you do in api.add_router("/model/event", router)
@api_controller("/model/events/") 
class EventModelController(ModelControllerBase):
    model_config = ModelConfig(
        model=Event,
        schema_config=ModelSchemaConfig(read_only_fields=["id"]),
    )

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

2 participants