Django Ninja
The Django Ninja library provides view decorators named after each of the HTTP operations used in REST actions. A decorated view will be registered for the appropriate REST call and automatically serialize and deserialize data into JSON format.
00:00 In the previous lesson, I gave you an introduction to REST and how it uses HTTP operations to act as an interface. In this lesson, I’ll show you your first glimpse of Ninja.
00:11 You’ll have to pay close attention, though. They’re sneaky and tend to hide in the shadows.
00:17
Ninjas are secretive, and so before earning their trust and getting them to come out in the sunlight, a little diversion. As I mentioned in the overview, I’m demonstrating the APIs I write using the command-line data-transfer tool called curl
.
00:32
Most Unix-based operating systems like Linux and mac come with curl
installed. For Windows, you may need to install it yourself. More recent copies of Windows have started shipping with it as part of some of the development tools. So, first off, check whether or not it’s on your box.
00:50
Once you’ve got it installed, you’ll be using curl
to do HTTP operations. It’s a very complete tool, and it talks all sorts of protocols. If it’s on the network, there’s a chance curl
can talk to it.
01:02
The most basic use of curl
is to just give it a fully qualified URL. It will go wherever you send it and print out the response it got. There are some command-line arguments, though, that you might find helpful. Appropriately enough for a course on Ninja, -s
is for silent.
01:21 It turns off the progress indicator and other verboseness, giving you just the server’sresponse. In contrast to silent mode is verbose mode. This tells you lots, including the headers being sent and received.
01:34
I’ll be using this occasionally to look at the headers coming back from the server. If you don’t specify which HTTP operation, you’ll be using GET. If you want to use a different HTTP operation, the -X
flag with the name of the operation is how you do that.
01:52
-d
specifies contents for the request body. This is used for calls like POST to send data. It can be used multiple times to send many name-value pairs.
02:04
And finally, -H
is for adding an HTTP request header. This example would post to the /people
resource, passing the fname
and lname
fields, and asks to be sneaky, silent—like a ninja.
02:23
Okay, you know how to talk to the server using curl
. Now, all you need is a server. I’m going to assume you know how to get going with Django.
02:30
If not, the intro lesson has some links to courses and tutorials that might be helpful for you. This course uses two libraries, Django and Ninja. So you’ll need to pip
install those two.
02:42
Then use the django-admin
command to create a new Django project. I’m calling mine Westeros
. My first Django app in the project will be called lannister
. Wouldn’t Game of Thrones have been even better if it had ninjas?
02:56
It had pirates. An age-old Internet dispute could have been settled. Don’t forget to add the lannister
app to your INSTALLED_APPS
property in your settings
file.
03:06
The lannister
app is only going to contain a Ninja-based API file, so you won’t need the usual view, test, admin, and model stubs that come when you create the app. If you’ve got all that done, then you’re ready to go.
03:19 Let’s go write an API. Lion banners will furl, debts will be paid, siblings will—well, let’s just leave that alone.
03:30
This is my first API call. I’ve created a file called api.py
inside of the lannister
app. Ninja doesn’t actually care where you put this stuff, but this is a pretty common place to do it.
03:42
You might also put them in your views
file, as technically, these are views. To define a Ninja API, you’ll need a NinjaAPI
object. That isn’t in this file.
03:54
I usually put mine in the urls
file. I’ll show you that in a second. Instead, I’m going to use a router. The router defines the routes for my API calls, and then I register those against the Ninja object, again in the urls
file. Here, I’ve imported the Router
class, so I can construct a router for the lannister
app.
04:15
Then I instantiate it. To define an API endpoint, you use a decorator on the view. The decorator is a method in the Router
class, and its name corresponds to the HTTP operation you want to perform. For my little Hello, World
here, I’m keeping it simple, so I’m using a GET. The HTTP operation decorators take several different arguments, but in the GET’s case, only one is required.
04:43
That’s the path of the endpoint. This isn’t the full URL, just the end part of it. You typically name this after the resource you’re fetching. Here, I’m just doing "/home"
, kind of a Hello, World
for API endpoints.
04:59 The endpoint is a view like any other view. The decorator provides a wrapper that registers it with the router and mangles the output so that it is a valid response for the view. Like all views, this one has a request object as its first parameter.
05:15
The simplest thing you can do with an endpoint is to return something that can be turned into JSON. A string or a dictionary is your most basic thing. The decorator automatically takes this JSONifies it, and wraps it in an HTTP response object with the appropriate MIME type set. With the endpoint defined, I need to do a bit of setup and register this router. Let’s look at Westeros/urls.py
.
05:45
Somewhere, you have to define at least one instance of a NinjaAPI
object. I’ve chosen to do that in the main urls
file. You can do this elsewhere and import it, but you’ll need this object to create your path definition. For simplicity’s sake, I’m going to do it here.
06:03
This imports a class so that I can instantiate it. And this imports the router that I defined in the lannister
app.
06:13
I create a NinjaAPI
object and then call .add_router()
. .add_router()
takes two arguments. The first is a partial path where the routes will be located, and the second is a reference to the router itself.
06:27
That "/home"
endpoint that I defined in the apis
will show up as lannister/home
. It actually goes one layer deeper than that, and I’ll get there in a second. Finally, you need to tell Django all about this good stuff.
06:43
You do that by defining a path with the NinjaAPI
object. The full URL for the Lannister home view will be /api/lannister/home
. Note that I didn’t say /
at the end there.
06:58 This is actually one of the few things I don’t like about Ninja. It doesn’t use trailing slashes. And as an old Django guy—that’s both someone who is old and old at Django—this feels wrong and inconsistent. But that’s the way it is.
07:15 Okay. With all that defined, let’s go run the Django server.
07:24
And I’ll open a new shell … and do some curl
.
07:35
There’s the full URL and the response. In the bottom window, you can see that a GET was done against Django, and it responded with the number that makes web developers happy, 200
. Let’s do that again.
07:49 This time I’ll use verbose.
08:00
The greater than signs (>
) indicate the stuff that curl
is sending. That’s GET
and some headers, the Host
, User-Agent
, and whatever it’ll accept back. The less than signs (<
) indicate what came back.
08:13 Let me just scroll down a little bit.
08:17
You can see that Ninja has set the content type to json
. That’s handy. One less thing for you to do. Then after the <
signs, you can see the house words. Actually, in season one, episode five, Master Luwin indicates that this is a common saying, but not their words. Their words are Hear me roar.
08:39 Anal-retentive geekiness aside, that’s your first API.
08:46 Next up, getting into an argument with Ninja. That doesn’t sound like the best plan, does it? Something pointy may end up somewhere unpleasant.
Become a Member to join the conversation.