URL Arguments and Query Strings
The Ninja library supports the use of query strings or path based parameters to provide arguments to your views. Both mechanisms take advantage of type annotations to automatically do conversion from the string format of an HTTP payload into a Python object as needed.
00:00 In the previous lesson, I showed you your first Ninja API endpoint. In this lesson, I’ll introduce you to dealing with arguments in your API. Ninja has multiple ways of dealing with arguments.
00:13 The one I use most is including them as part of the URL, the same way you do in a Django view. Ninja also handles query strings if you want to get old school or you need an argument to be optional.
00:27 It’s easy to forget that everything in HTTP is a string. In the old days of Django, you couldn’t specify the type in the path definition, so you had to remember to convert things by hand.
00:37
I can’t count the number of times I forgot to convert an ID into an integer and messed up a view. Thankfully, those days are gone, and Ninja being a modern interface, uses type annotations to help make this simpler to define. Since this is a new lesson, I have added a new Django app. This one’s going to be called dothraki
.
00:57
Don’t forget to add it to INSTALLED_APPS
. A new app means a new router. Just need to do the same thing I did with the lannister
app: import the router that I’m about to show you, then register it with Ninja, and you’re good to go. Let me scroll down here.
01:17
Note that the path doesn’t change. As the dothraki
app is inside the API object, registering it is sufficient.
01:29
Here, I’m inside the dothraki
API file. This view shows the first technique for adding arguments to your endpoint. Simply add an argument to the view function definition, and Ninja will process it as a query string key-value pair.
01:45 Let me show you how it’s called.
01:56
A quick aside before I talk about the Ninja part here: note that I’ve surrounded the URL in quotes to pass it to curl
. The question. mark is a special character for some shells. I’m using Bash. It doesn’t care.
02:08 Other shells, like Zsh, do care and will give you strange errors. If your shell gives you trouble, just wrap the URL in quotes and it’ll be treated as a single string.
02:19
Right, that said, let’s talk about what the code did. That gender
argument to the view function definition becomes a key with the same name in the query string. Passing in f
as my value gets me greeted as the queen.
02:41
As I didn’t specify a default, Ninja enforces this argument. If I forget it, I get an error message. Handily, this is also inside of JSON. That compact response is a bit hard to read. Let me do that again using the json.tool
module in Python.
03:07 That’s easier to read. This mechanism for errors means that if you’re using view or react, you can still parse the response and show the message in a pop-up dialogue if you wish. More on error handling in a future lesson.
03:21 Let me add another view. I mentioned that Ninja uses types. By specifying the type in the argument list, Ninja will automatically take the query string and do an appropriate type conversion. Still using the question mark, so still wrapping it in quotes.
03:44 Then there you go. Three horseys.
03:51
The more Django-esque thing to do is to put your arguments inside the URL itself. You indicate that you want to do this to Ninja by using curly brackets ({}
) inside of the path. You can combine this with annotating the argument in the view function definition and get the corresponding type conversion. Strings don’t need to be converted, but it is good practice to tell other programmers what you’re expecting.
04:26 Who doesn’t love horse jerky? Finally, you can also use a notation similar to how Django paths are defined, putting the type directly in the URL. This is actually my preference.
04:41 It just feels right to me to have the info in the place where it is used.
04:53 And there’s the result, fermented horse milk for everyone. Because Ninja converts what you return from your view into a response object for you, you don’t have a chance to affect the response object.
05:08 There is a way to get at it, though. Why would you need to do this? Well, say you want an extra header in the response or need to specify a cookie. You need the response object. Let’s go look at how this is done.
05:24
You might have been able to guess this, as everything else was done with types as well. All you need to do is include an argument to your view with the HTTPResponse
type. That’s from the django-http
module. Ninja sees the type and treats the corresponding object as the response.
05:43 Since you’ve got a reference to the response inside of your view, you can set a cookie or add a header or do whatever else you want with it. Let’s take a look at this in verbose mode.
06:04 And here at the bottom, you can see that the cookie was set, and the server has told you that the sword is all bendy. So far, you’ve been returning strings from your views.
06:16 Ninja has a mechanism for serialization called schemas. That’s what’s next.
Christopher Trudeau RP Team on March 30, 2023
Hi Tom,
Yeah, curl is giving you exactly what is coming back. Check out the “-w” option, which allows you to output something after the response. You can use it to do things like writing “X bytes downloaded”. In your case, -w "\n"
should give you a newline after the result.
Become a Member to join the conversation.
TomDevUK on March 30, 2023
Question about weird curl behaviour. It looks like the response I’m getting from Ninja API doesn’t contain a trailing new line so after executing curl command the command prompt doesn’t start in a new line but from the next character after the end of the response. I have not seen this behaviour when I was testing DRF, any ideas how to fix it?