 Welcome to DjangoCon. My name is Nina Zacharenko. I work for Reddit and we've been using this stack pretty extensively on our internal tools and it's worked out really well for us. To show of hands, how many of you guys write JavaScript? No JavaScript? It's awesome. A fair amount of you. So I made a kind of a little sample app that goes through all the concepts that we're going to be discussing. So if you guys want to clone that, I'll be going through a lot of code that's in this app and you guys can follow along. So kind of doing this a little bit differently, I think this will be a little bit more fun. So Django templates are not my favorite. They're, yeah, deal with it. Don't mean to offend anyone here but it's my point of view. So you know, they're kind of really slow. If you want to submit a form, you have to wait for the whole page to refresh. Template tags are kind of hard to understand. If you forget to end one, your stuff is broken. It can be hard to debug. It's difficult to unit test. And if you're actually working with a front end dev, sometimes it's kind of difficult for them to pick up the template tags without knowing Python. And tags are pretty annoying. So forms get complex really fast. You kind of sprinkle in a little validation logic over here and abuse some template logic over there and all of a sudden, you know, would you like meatballs with your spaghetti? So in my humble opinion, why end points are better? They're faster. You can have a single page app, you don't have to wait for the whole thing to reload. You can swap JavaScript frameworks pretty easily. There's a whole slew of them out there. And once you have your end points set up, they're reusable. So let's say you want to write a native mobile app, well, you know, your backend's already there. So that's pretty awesome. You can dog food. So if your end points are public, you can use them internally. Kind of work out all the kinks. See what's working. See what isn't. They'll be the first one to find out if there are any problems. That's really a huge benefit. The other nice thing is that REST frameworks are standard. So, you know, if you have a new front-end dev, chances are that they've already seen this. They've worked with this kind of structure. It's easy for them to understand. It's nothing new and they can get started right away. The JavaScript framework, why not Angular? There's tons of benefits to Angular. There's an MVC framework. The responsibilities are separated. Single-page app, no refreshes, much better user experience. And the scope is this magical thing. It's a way to bind variables between your front-end and your controller. So no jQuery, no crazy JavaScript magic. You set a variable on your scope and it's accessible in the template. Angular is also very easily unit tested. Much better, I think, than kind of comparing, you know, in your unit test. Does my HTML match what I expect it to? It's kind of hard to be dynamic when you're doing that. So the bad, you have to use JavaScript. It kind of seems like a bunch of you already do. That's good. But I overheard in the elevator the other day, someone's like, I don't like JavaScript. It's just too many curly braces and semicolons. Yeah, that's not a good reason not to like JavaScript. So obviously, other languages are not as elegant as Python. But it's the language of the web. It's not going anywhere. You'd be doing yourself a really great disservice, avoiding learning it because you don't like the way it looks. Sorry to call you out, random elevator person, but it's true. So if you don't like Angular in particular, it's pretty easy to just swap out to another JavaScript framework. You got React and you got Ember and you got Backbone. And who knows what's coming next. So they all have their strengths and weaknesses. A great talk about that is my co-worker, Brian Holt. He did a presentation about choosing a JavaScript framework, what the strengths and weaknesses are. So if you guys can't read that, that's http bryanholt.me. And I definitely recommend that you read it. It's one of those funky reveal JS presentations. So just make sure you hit the down arrow if the presentation seems a little bit short. So I put up that GitHub code link earlier. Here it is again for anyone who missed it. We're going to go ahead and use all the concepts that we're learning today to build a Twitter app. Our requirements are pretty short. Probably won't be seeing this out in the wild pretty often. We want to display a list of tweets for all users. We want to narrow down that list and only get the tweets for the logged in user. And then we also want to show the profile for that logged in user. It doesn't take a ton of code to get this all together. It's actually pretty impressive. So the endpoints that I'm using are created with Django REST framework. Pretty easy to create a REST endpoint for your application. I don't know if any of you were at my talk yesterday, but I kind of explored that in more detail. For those of you looking at the code, the beef of the DRF stuff is in serializers.py and permissions.py. And then the routing is done in URLs.py. So here's our model. Pretty simple. We have a foreign key of user because we want to know who made the tweet. We have a regular chart field for the text and a timestamp of when the tweet was created. This one? This should be on. Yeah. I'm sorry. How about I do this? Does that help? Talk to you all like this now. I'm going to have to deal with the static while I do. How about that? Is that better? I'm just going to have to shout. Testing. Good. Okay. I'm going to take this contraption off the line. Can everyone hear me now? Yeah. Awesome. All right. Just because people couldn't hear me, could you raise your hands and ask if there are any concepts you'd like me to re-explain? Y'all good? All right. So our endpoints are going to look like this. They're really simple. We have an endpoint to fetch all the users, an endpoint to fetch just one user, an endpoint to fetch all the tweets, and then an endpoint to fetch a tweet by ID. So when we call our tweets endpoint, this is the kind of response we're going to get. It's just a list of JSON tweets that contain the fields that we've defined in our Django REST framework serializer. The next thing we're going to talk about is configuring Angular for Django. There are definitely a few gotchas that you need to be aware of when you're using it right off the bat. So the first thing you need to do is fetch an Angular file and include it in your template. For my mini project, I just fetched it and put it in a local lib folder, but it's best to use CDN. If there are any updates, you kind of get them automatically, you don't have to worry about maintaining yet another library. And the way we enable our front end to be Angular is by using an ngapp tag. Can everyone see the bottom of the screen? So the most common place you would put it is in the HTML or the body, but if you only want some little part of your app to be Angular, you can even throw it in a div. So really flexible. I called my Angular app, Twitter app, so very creative and original. Angular tags and Django template tags conflict. They're both double curly braces, and that's kind of a problem. If you just try to throw some Angular on your Django page, some things are going to barf and not very pretty. So the way to get around that is either to tell Angular to use a different kind of tag. So for example, I like using double square brackets, or you can use the Django template verbatim tag. So I very much prefer the first way, because if you go the second route, you're just going to have tons of chunks of verbatim tags all over your template. It gets messy, not really great, but it's an option for you if you want to use it. So this is how we tell Angular to use a different kind of bracket. It's actually a really great feature that they've provided this, and we have options. The second thing we want to configure is our CSRF tokens. So if you read the Django docs on EJAX, they'll tell you to do this. So you need to tell Angular that this is what the CSRF tokens are, this is what they're called. And then in your Django views, you want to use ensure CSRF token to make sure that that token is generated, even if the CSRF token tag is not present in the template. So kind of handy and cleaner, and I think it's a lot more explicit too when you're looking at the view. If not all your views are CSRF protected by middleware, you know which ones are going to be passing that token back. The next important thing in our configuration file is we want to tell Angular to stop stripping trailing slashes. I don't know why it does that, but that doesn't really work with Django, because Django loves trailing slashes, they're everywhere. So this is actually a new feature in Angular 3, so be mindful of that. If you're using an older version of Angular, there are some kind of hacky ways to get around it. You have to add on a trailing slash that's escaped in a string, and then you can't use some of that Angular magic where it kind of can guess what your endpoints are structured like based on Rust, and you have to do a little bit more configuration on the Angular side as well. So this is what an Angular resource looks like. It's a factory that lets you create a resource object based off a Rust endpoint and interact with it really simply. So to kind of walk through the code, Twitter app.services is what my services module is called, and then ng-resource is actually a separate JavaScript include that you have to be mindful of because it's not part of the core Angular code. And here we define a factory that's based on our tweets. So when we create an object called tweet in JavaScript land, it's aware of this URL, and there's some kind of magical binding going on. So here are some of the default actions you get with the Angular resource. You kind of get all those HTTP verbs. It's aware of get. So if you have an ID defined in your resource, like I did here, so there's that the, I don't know, what is that symbol called, the two dots, colon? Colon. Yes. So colon ID is kind of an important thing to note there because when you use this kind of built-in method, you call get. It knows that an ID is expected, and so when you pass one in, Angular knows that you're getting a single resource, it's an object, it kind of does magic and transforms it to be that way. Whereas when you call query, it knows to expect a collection, and it's going to call the root of that endpoint without the ID. Does that make sense to everyone? See some nods? Yeah? All right. So here's how we would create a new object. It's really simple. It's not quite as messy as something like jQuery, Ajax. So we called our resource tweet. We can just call new tweet, set some properties on it and call save. That's Angular magic for you. It's pretty awesome. So there are two ways to interact with these resources. The first way is callbacks. I'm sure many of you have heard of or experienced callback hell. It's out there. So when you call tweet.get and you pass in an ID, if that's kind of it, what you're going to get back is a promise. So you don't get anything back right away. You kind of have to know when the server has responded and then do something with that data. So here's the callback format. We're passing in a function. We're taking in a tweet. And then we can do stuff with that object once that server has returned. The newer way of doing this is it's called promises. They're much cleaner code. In my opinion, you can chain them. So instead of passing in a callback function, you instead call .promise then. And then your function that gets called when that data is returned is there. And you can chain these promises. So this promise only takes care of a successful request. If there's an error, you should chain another promise on. And then you'll get that error code back and the status. And you can do something with that. So for example, if it's not authorized, you know, display the correct message to the user. So the scope is, like I mentioned earlier, really my favorite thing about Angular, I like to call it Outer Magical. You change something in your controller. It's displayed on the front end right away. You change something on your front end and your template. And it's there in the controller. Magic. Magic. That's how I felt when I first learned about it. So let's move on to controllers. The syntax for creating one is kind of similar to how you would create a resource. So here Tweet CTRL is the name of our controller. And we call a function. But an important thing to note here is that these are dependencies. So by passing in these arguments, we're telling the controller that we need a handle on scope. And we also need a handle on Tweet. And that's that resource that we created. So now we can freely use it in the controller. So here's the meat of our controller. We have our query function. And that satisfies our first requirement of wanting to get all the tweets that exist. Here you see I'm using a callback. And when that query returns, we want to set scoped up tweets to the response. So as soon as this function is done, they pop up. The other thing, the other function in our controller is used to submit a Tweet. So we use that same syntax that we saw. We create a new Tweet. We pass in the data that was in that input box. And then we call save on it. And the last thing that we do is pop that Tweet right onto the top of our stack of current tweets. And it's displayed right away. So fortunately, you can't get rid of all the Django templates. You need one. It allows you to pass information back and forth from Django land to Angular land. It lets us know what the static URL path is. So that we can include those files. It's kind of useful. So you can't get rid of it. Here's an example of how you would pass some template data back into Angular. It's a little bit hacky, but it works. And we actually throw this on our base template page. And it instantiates a quick and dirty little service. I call it off-user. And it kind of runs a piece of code on the page and just returns that result. So we can actually go into the Django user and get some useful information back from it. In this case, the ID. I'm not sure where I found this hack, but it's actually been really useful. So however the author is, thank you. So this is how we do UI routing in Angular. Instead of using Django templates, we're going to be using Partials. There's a lot going on on this page. So let's kind of go through it one by one. And the first thing that we note is that URL provider, the default, that's the default route. So if someone tries to type in a bunch of stuff in that URL bar, they're just going to get kicked back to here. The URL is what that URL will look like to the user. The template URL is where that partial is stored. And the controller is kind of the important bit. That lets you know, that lets Angular know which controller to associate to which template. There is a different way of doing it. That's similar to NG app. You can throw that controller into any HTML tag. But I find this way to be much cleaner. All your controllers are defined in one place. You instantly know where they're getting called. So routing in Angular is pretty simple. You drop UI view into a div anywhere on your page. And that's where the Partials are going to be dropped in. So it's a lot different than something that you include because it's also aware of state. You can pass variables back and forth. You can use them as conditionals. So very powerful. Your Partials are just vanilla HTML and Angular. No Django necessary. I like to keep them in an accessible static folder. I can show you guys one. Let's look at some code. If we can reserve our questions for the end of the talk. I'll have to show you guys afterwards. Chrome full screen does not want to give up. So I didn't include any information about testing in this talk. I wasn't sure if I would have time. But test all the things. Do it. It's just so much easier and nicer. The Angular documentation is pretty good. My experience with it, there are some cons. The biggest one to me was when you get an error in your Angular code, it's pretty indecisorable. Indecisorable for a bull. Excuse me. It's all anonymous functions and callbacks and something happens. You're just like what? But it kind of figuring out what's going wrong comes with experience. So just keep at it. Don't get too frustrated. Use that debugger statement in your JavaScript. If you have Chrome DevTools open, it'll just stop there. Use prints. They're okay. We all use them. It's okay to admit it. So demo time. Crossing my fingers because this didn't go so well the last time. But I'm going to show you guys my Twitter app in action. Here it is in all of its glory. Here we have all the tweets from all of our users. They're really cool and creative. We all want to read them. And here's my tweets view. It's so fast. Nice user experience. No page reload. It's pretty instantaneous. And it doesn't, you know, even when you have a ton of data, it's not super bogged down. And here we have our profile view. So I know I'm a great web designer. Thank you guys very much. But the cool thing that I want to look at is, let's see if I type that right. Here's our Django REST framework. Brasable API. This is awesome. Definitely one of the features that I love most about it. It's super easy to use. For example, here's a dropdown. Oops. demo time. We can call options and kind of see what's available on our API. Here, this is the root. So from here, we can kind of navigate down. Look at our tweets. We get a tweet list. So here we can see all the data that's coming back to Angular. We can also submit data back. So we can either do it from raw data or HTML. I have a, or an HTML form, actually, which is really nice. So I have a validator set in place that's going to return an error if my tweet is less than five characters. I get a bad request with the error message that I specified. Django REST framework is also really smart. So I have a model field that is only 140 characters. So I put a bunch of text in here. I just feel like I'm, you know, doing this not long enough. Let's see. Here, I have a better idea. Copy and paste. We'll get another bad request. I can't see this on my screen, so I'm just going to assume everything is going great. Let's go back to our API root and take a quick look at our users endpoint. So here's where we, here we go. Look at my awesome tweet. Here's where we get back. All of our users, properties about them, first name, last name, user name, and then a collection of all their tweets. So this was super easy to create. And Google Drive. The internet was down earlier today, so that was definitely very, very nerve wracking. That's it for my presentation. Feel free to find me afterwards if you have questions. I love to talk about the stuff and I hope you guys enjoyed my talk.