django-ninja
django-ninja copied to clipboard
Calling NinjaAPI.urls twice results in error
Hi @vitalik !
First off - what a wonderful library! Thank you for your efforts.
I have a question related to url resolution and how it intersects with testing.
To start, calling .urls on an API instance twice results in the following error message:
The code -
test = NinjaAPI()
test.urls
test.urls
Results in -
ConfigError: Looks like you created multiple NinjaAPIs or TestClients
To let ninja distinguish them you need to set either unique version or urls_namespace
- NinjaAPI(..., version='2.0.0')
- NinjaAPI(..., urls_namespace='otherapi')
Already registered: ['api-1.0.0']
It appears this is due to the _validate() method within NinjaAPI that's called by urls. It implicitly checks to make sure .urls have never been called before. I found this to be a little confusing, particularly given the error message which implied multiple instantiation rather than multiple access. Why is retrieving the .urls twice considered to be an error?
Taking this one step further, my real goal here was an attempt to test the API. Recognizing that testing is undocumented today, I tried to use the TestClient client provided by ninja. As an example:
from ninja.testing import TestClient
TestClient(test).get('/hello') # test is the API instance instantiated above
I thought this should work given the TestClient signature - it expects a NinjaAPI or Router instance. However, this consistently failed with the same ConfigError message above. On digging in, it became clear that this was caused by both Django's URL config calling test.urls and the TestClient calling test.urls.
I was able to work around this by using a Router and testing the Router instead of the API directly - but I was surprised that I couldn't simultaneously test the API and use it in a URL config.
I was left with the following questions:
- Why does the API strictly validate that urls are only retrieved once? If it's incorrect to ever compute the URLs more than once, why not cache instead of strictly validate?
- How, if at all, would one test an API directly rather than a Router? Should the documentation or TestClient be updated if it's not possible or recommended?
If the changes are reasonably straightforward here, happy to help with a small PR.
hi @jlucas91
basically the problem is that each operation(path) has is it's own url-name - and if you include it twice it will have a clashing naming
Indeed this is not perfect solution - and I'm looking for some more elegant way to deal wit this
Could you say a bit more about what you mean by "include it twice"? It makes sense that we have to validate to make sure url paths don't clash - though I would imagine that could happen once on instantiation, rather than access of the URLs?
Do you have any thoughts on whether it is/should be possible to test an API directly (rather than a router)? Asking because I'm working on some basic testing documentation and right now I think I need to include the router for testing to work at all.