RESTful and HTTP APIs in Pyramid Transcripts
Chapter: A nearly RESTful service
Lecture: Extending JSON renderer for custom types

Login or purchase this course to watch this video and the rest of the course contents.
0:01 Let's change our service around just a little bit so that it returns or basically uses rich types in the data layer.
0:09 So if we come over here, and we look at this load car bit, you can see right here we're using a dict reader on our csv file here,
0:16 now this is just a temporary thing, until we get to a real database which as I said, we'll get to later. So, right now, everything that we're storing
0:24 is basically straight up dictionaries and Python dictionaries, json super, super similar so those are really easy to serialize to and from.
0:32 But, keep in your mind, we want to have a better architecture than just passing dictionaries, and we're probably using an orm
0:38 which itself works in these rich types, not just in dictionaries, again. So let me change this data access layer around a little bit
0:47 so that it works in terms of a car class that I'm going to create, and then we'll try to run the same code and see that we'll run into a problem
0:55 because we won't be able to serialize it by default in the json serializer. All right, after a little bit of juggling, I got this all working great,
1:04 so here you can see I have created a car class, now imagine like I said, this is coming from an orm, like sqlalchemy or mango engine
1:12 and really the thing that's important is just that it's its own custom type
1:16 and what we learned here, we can apply to all different situations including orms, so we have the ability to create one of these
1:22 and it has basically exactly the same properties that we had in our dictionary, right so there's not really a major change there,
1:30 and it also has the ability to be given a dictionary convert itself and because I use the names to be identical to what's in the dictionary
1:38 we can use this ** dict you know convert dict to keyword arguments thing here and that will create it nice and easy.
1:45 I also taught it how to go in reverse so given one of these instances how do I create a dictionary out of it and this little bit of functionality
1:54 is going to be super important,. Next, let's look over here, I made some very very minor changes let's just look at the put update auto method
2:03 this is basically the same for all of them that work this way. Recall we were getting the dictionary back, as using the json body here
2:09 well, now that's not enough because our data layer wants cars not dictionaries,
2:13 so we just use this car from dictionary thing to convert the dictionary into cars,
2:18 right, there's still a validation that we're kicking further down the line we'll come back to that later, but for now,
2:23 this basically is the only change we have to mess with. Now, how are we doing— let's have a look, so I come over here, great so here's the same code
2:34 and if we do the same get, remember this gives us a list of json objects it's all the cars, except for now it's not, right
2:41 this is exactly the error we saw in the slide, this thing is not json sterilizable, So now what do we do?
2:48 Well, now we need to start looking behind the scenes at how these renderers actually work,
2:53 and we'll see they're very configurable and we can plug in new ones, we can create our own, and it's a really nice system
2:59 but by default, this wouldn't work. Now just to be fair, if I imported json, so here I go something like this import json and I say json.dumps (car)
3:11 that crashes, right, it's basically that the json module doesn't know what to do
3:17 and so pyramid just delegates at the json module what's it supposed to do right. And we can't call like I said stir on this because it'll just give you
3:26 basically the type name and the memory address, also unhelpful; but what we do have that's helpful is this method
3:32 if we could somehow say, hey json serializer, if you run into a car here's how you turn it into a thing that you could then know how to serialize
3:39 because dictionaries obviously serialize well, so let's look at that. Down here, we've got our allow_cors, our register_routes,
3:49 this is basically the setup for the main entry point for our web apps, so let's add one more, let's call them configure renderers
3:58 and we'll pass the configure, so let's put this down at the bottom we'll do a little def, so we've got our config thing here
4:08 and our config has an add renderer here, and what we can do is we can give it a name like json and put some value here
4:17 so we'll call this json renderer and there is already one of these created right
4:22 we can say json, and our view config says I want the renderer to be this and there's one of these created, but it's just the default one
4:29 so let's go and configure this a little bit differently; we can come here and there's a thing called json
4:35 which is part of the pyramid renderers, notice that so we're going to create one of these, now there's all sorts of stuff that we can set here
4:42 but one of them is the level of indentation, so right now everything we get is minified, maybe I want to have a more readable output
4:50 so we can set it to indent like that, but the thing that we really need to do is go to this thing and say add adapter, notice how it takes the type
4:59 and then an adapter and the adapter is a callable function really so the type, car and what can I do to give it a callable
5:10 that will take a car and then convert it into a dictionary or something like that, let's go like this, let's go given a lambda that passes a car right
5:19 so a function that takes a car as an input what's the return value car.to_dict like that, ok
5:25 now this looks like we're pretty much set up and ready to go PyCharm thinks that is misspelled, I don't think so.
5:33 Okay, so we're going to, instead of using the built in default json implementation
5:37 we're going to create a new one, we're going to tell it to do like pretty print basically
5:40 and we're going to add this adapter so if you ever run into a car, and no matter where it is in your object graph
5:47 here's how you convert it to a thing you can deal with, this should fix our problem, all right try again, moment of truth, refresh button—
5:57 oh, two positional parameters, that's right there's not just the car, there's some other contextual information passed here
6:04 so I don't care about it, I'm going to put the underscore but of course, we do have to have the position all place if we're to go
6:12 this isn't javascript right, it's a proper language. Okay, here we go, now look at that— so we come over here look at the raw data,
6:20 look, now the raw data is like this, like if I do a view source, if I can get it to do a view source, the view source is now pretty printed
6:27 just to show you what we got before let me turn that off for a minute and refresh this page— now you can see it's the minified version,
6:34 maybe you want to ship the minified version, but it's probably really not saving you that much,
6:38 and this is a little bit nicer for people to look at and try to understand so you've got to balance developer friendliness readability
6:46 versus peer performance of dropping a few back slash ends. It's up to you, but if you want it pretty printed,
6:53 we can configure the json renderer to do that, and more importantly, we can add these adapters like hey,
6:59 if you want to serialize a car, like we give it a list of cars, and for each one of the items in the list,
7:04 it's going to call this function, pass in the car and some extra info,
7:07 and then for that car instance, we are just going to use our little to dict method. So we should be in business.
7:15 Alright, so things are looking good over here, now let's take one of these individually, and see what happens if we try to get it, right,
7:23 if we look over here, make some room, if we ask one individually, it's going to call this, which is going to return a car and it's using the json
7:31 whatever the name json means, right, we've kind of overwritten that in that sense, go here, we'll try that one, again, it comes out looking great,
7:39 in fact, it's even pretty printed. If I click pretty print, it indents a little differently, but otherwise, other than that right,
7:48 these things basically agree on what pretty printing is, if they could agree on tabs, right. Awesome, so now we've fixed our problem,
7:56 we've taken this renderer, and we've added an adapter and we've done some more stuff, but this also starts to unlock some more possibilities, right,
8:04 so down here, what we did is we created some instance of an object and we registered it, in pyramid to say
8:10 if somebody says json do this, right, use this, and if we go and look at this object, you can actually see some of the things that it's doing
8:20 it has add adapter, this is a really important part, callabale, it defines an internal implementation of how it renderers at each step along the way.
8:29 So, pretty much that, this callabale, this function, and some initialization stuff, that's really all you need to do to add any sort of renderer.
8:41 So we're going to use that concept to add a csv renderer, an image renderer, and maybe even more.

Talk Python's Mastodon Michael Kennedy's Mastodon