We're onto our last mini-lecture about views, and it's a big one. It's about generic views. It's a really big lecture so that we end up with little tiny views with one line of code. So I've been building up views and we've talked about inheritance with the templates, and now we're going to talk about inheritance and views. And we've been inheriting all along with views. So here we are in the views.py. This whole thing, these particular kinds of views, we define them in views.py, but they're very informed by the content of model.py, which means that views are constructed automatically just looking at the data in the models.py. So it's again sort of the logic of don't repeat yourself. If you have a thing in models.py, you've defined exactly what the fields are and things like what the help text is for this field and what the description for the field is. That has nothing to do with the database, but it can inform the views. You'll see how it all fits together nicely, but sometimes we use these super awesome techniques, we end up with a little tiny bit of code and it's really important to deeply understand that tiny bit of code because you can sort of just fade away and not realize what's going on because this code is so cleverly reusing a ton of other code and pulling stuff in from other places. So if you go all the way back to when we talked about SQL, the four basic operations are put data in a database, get data out of a database, delete that data, or update that data. CRUD, create, read, update, and delete. And we're going to build a bunch of things, whether they're ad things, or auto things, where we've got to insert an auto, update an auto, delete an auto, list all of the autos, insert a cat, delete a cat, list all the cats, update a cat, right? And so we have a bunch of user interfaces that we're going to build over and over and over again. And as you build your own projects, you'll probably have four or five tables and then little CRUD user interfaces for each of the tables. And sometimes you make them a little different and there's pretty stuff on them and they're customized. But surprisingly often, these things just look the same and we end up repeating ourselves, which is something we don't want to do as software developers. So here is a simple CRUD application. This one here is only read and details. So we have a list of cats and then you click on the cat list and then you see the data for a particular cat and then a link back to the list. So this is like a detail page. But we're going to do a lot more than that, but I just want to show you how these generic views work by keeping things very, very simple. So we're going to talk about a generic view in the list and the detail, which are two of several generic views. So this is our gview application, and here is the urls.py. In this gview, it has a list of cats, an individual cat, a list of dogs, an individual dog. And so you see this sort of repetition. And I'm putting so many of these in here because I'm going to show you sort of different approaches to implement them using less and more detail and less than more inheritance. So they're all kind of the same. I give them a name, some have integer primary keys, and away you go. And so here is the cat list, I'm going to start with a template. So we're going to expect in the cat list template that there is a context variable called cat_list, and that is a list of cat objects. And then we're going to iterate through the cat list, however many cats there are, inside of a list, and generate an li tag, and then create a link URL, and then pull out the name of the cat. So the cat has a name and the cat has a primary key. And so we are going to generate a link to the cat Sophie, and underneath that link is the link to slash cat slash 12, whatever that number is. And if the cat list is empty, we're going to say there are no cats in the database. Now, we've actually got a script that you use to preload all of this data. So there's instructions in the sample code as to how to preload that data. Take a look at the readme for it. And so if we're in the detail page, we're going to pass a cat object in, and that has a name, and then we want a link to go back to the cat list. And so again, we're using something from the immediate previous lecture where we're using the url macro, passing in the name of a view within an application. So this is the gview applications, the cat view, and then for an href, that makes a valid link with the string go back to list to be the thing that that does. So we're going to build all this stuff, and that's the basic idea that template and the HTML, that's how we're going to do it. But we're going to look at how the views work. And again, this is a reminder of the DRY principle, the don't repeat yourself principle. Again, sometimes this DRY principle gets us in trouble because the idea is that some bit of logic is placed one place and reused as many places as possible because don't repeat yourself would probably be as well described by calling reuse, reuse reuse, reuse. Do it once and then reuse it as many times as possible, so that if you have to fix it and you've got a bug in it, you don't have to find the 49 places that you put all this code. And because we do the same thing over and over and over again, cats, dogs, horses, we do it over and over and over again, cars, the idea that you have a list view, a detail view, a edit view, etc., it's a common thing and really if you're going to do this stuff, why not make it look consistent and function consistently? If you have one developer build the cats editing interface and another person develop the dogs editing interface and they let go off the same, go off in their own way and they got some groovy design but it's different, you know, who cares, right? It's inconsistent. You still want a beautiful design, but you want the cats data and the dogs data to make sense with that consistent design, so both of them can have a nice design. So we got templates. The templates expect variables, like the list expects a thing called cat_list or dog_list or whatever, and then the cat detail just has a cat variable in it, and then we call it. So if we just forgot about all the stuff that we're about to learn and we just wrote a view, it would look like this first one, this CatListView here. And so we would inherit from View. We're going to go to the database, we've imported the cat model, Cat.objects. This is the way to query all the cat objects and get a list of cat objects and put it in the variable stuff. That's what Cat.objects.all does. Now, we've done this before, like in the shell, but now we're doing it in actual Python code in the views. Like I said, views are where all the stuff happens. So that says make a database call, load all the cat records, turn them into objects, and give me a list of those objects. And then I'm going to pass in the context into the template, the gview/cat_list.html, I'm going to pass an entire list. And if you go back and look, there was a loop in the template that printed out Sophie, Frankie, and made links underneath them into the detail page, okay? So this is how we would do it if we were going to not repeat ourselves. Okay? Now, this next way of doing it for the dogs, we're going to do it another way. And so what we're going to do is it looks like it's more work, but it's more reusable, so the stuff that we're doing here. So what we're doing is now we have a DogListView, which is just a class, and we're going to create an attribute variable in this object called model. And we're just going to say that this model for this particular one is Dog. So the idea now is in this get method, we take this code right here and everywhere we said cat, make that be generic and have it be driven by this one variable. Okay? Now the tricky part that makes this a little tricky is sometimes we're just using the model, and then other times we are going to actually turn it into a text string. So if we take a look at this, we have this variable model and in the get request, self.model is the way to refer to the particular instance that we're in, that model variable. And so this meta.verbose_name.title to lowercase, you could figure that out by yourself by going to Stack Overflow eventually, that's how I figured it out. I wanted to get a lowercase version of the model name. So the model's name is a string D-o-g, which is not the same as the Dog model, okay? And so that just is a way, model name is going to be lowercase dog. But if model is Cat, then model name will be lowercase cat in this bit. So I'm trying to make reusable code. So yes, the reusable code looks a little more complex because it's generic. But you'll notice that I'm creating a variable called modelname underscore list, because I'm just concatenating it together. So it's modelname and it's going to be dog underscore list, so that's what's going to happen. I am going to talk to the model and retrieve all the objects. That's okay, I don't have to change it to a string, self dot model is Dog dot objects dot all, so then I'm going to get a list of all the objects in stuff and I'll put that in the context and then I'm going to go get myself a template out of the gview folder with the modelname underscore list so that what used to be cat_list in here is now dog underscore list, I'm concatenating it together, and I passed the context in. And so then when that happens, then you get a dog list and a list of dogs and away you go. So what I did is I generalized this code and put it in here and then I passed in in a sense to the object that was made from the DogListView class the actual model that I wanted it to operate on, okay? So I do this to give you a sense of how this works. You can do the exact same thing for horses by doing this. And that is, you import the django.views generic right here and you say, I'm going to make a class called HorseListView. I'm going to extend not just View, but generic.ListView. So this is a generic class, you can go look at the Django documentation for this. It's a generic class that does a list view in general. And the rule for the class is you have to add one line here to say which model it functions on, and that's it. And that's because the get code is already in this model. We're extending that model. We're inheriting all this code, not from DogListView but instead from generic.ListView. So we took something that was five lines, a little more generalized, it's like eight lines, and now it's one line. And so that's how the extension works, but you have to trust and you have to go read the documentation for ListView to know how it is that you inform it as to what model you're supposed to use. So I want to show you a little bit of how this is happening by making one of these ListViews that's mine, it's not as cool as the real Django Listview, just to give you a sense of what's going on behind the scenes in the Django ListView. So I'm going to make a new class DJ4EListView, and then I'm going to extend View and then I'm going to have a get method and it's going to be all this code. It's looking for a variable called model and you'll notice that it's not defining model up here because it's intended that this is a class that's going to be reused. So I'm going to say, oh, well, whatever the model is that's been set up here by the class that's being created while we're extending it, go grab that, convert it to a text, get the title of it and then convert it to lowercase, make that model name. Whatever the model is, retrieve all its objects and put it in stuff and then put modelname underscore list, in this case car underscore list, and then pass that list into the template and then render gview car underscore list context, okay? So this is not doing anything per se. DJ4EListView is creating a class that I'm going to extend later, and I'm going to extend that two lines later. I'm making a CarListView that extends DJ4EListView and the only thing I need to do to get all of this code in here is extend it and then I do need to add model equals Car. So you'll notice that CarListView has the exact same syntax as HorseListView, right? HorseListView, you basically tell it the generic.ListView tell what model to work on and then generic.ListView does at all. And if you look at CarListView, it says, use this generic ListView that I just invented to show you the source code of what it is, that's the source code behind the scenes. Like I said, it's way more complex and sophisticated than what I did. This is the crudest, simplest version of an extendable generic ListView. But when it's all said and done, you don't write any of those versions. You literally make a list view and tell what model is. You make a cat view and tell it what model it is. And you just reuse the ListView over and over and over again. So, the fact that I give you four different ways to do this, maybe five, four or five different ways to doing this, the real way to do it is one way, but when you look at code like that, you're like HorseListView is extending generic.ListView and the model is Horse. I'm trusting a lot. And the answer is yeah, you get used to it. And now the code you have to write is only two lines of code. And you have to write the template still, because it's going to call your templates, but it knows the name of the template by looking at that horse, right? It knows, oh yeah, horse underscore detail, right? or horse underscore list, and so this is the actual detail page that shows you the horse and goes back to the list, etc., etc., etc. So using these generic views, you can make things really short and really succinct and really simple. So, generic views are excellent, they allow us to produce lots of similar pages without repeating ourselves, they keep your code consistent. The repeating yourself doing the same thing over and over even though it seems quick to cut, paste, change, cut, paste, change, cut, paste, change. If you really want to build reliable code and code that's thousands and thousands of lines with hundreds of features, you don't want to be pasting the same thing over and over. And so less lines of code means fewer mistakes. So, this is kind of the end of our talk about views. It's really where we're going to start doing most of the work. The URLs, the models, they sort of don't get the kind of activity. Although we are going to talk upcoming about forms, which touch on views and they touch on models and they touch on templates. So forms are one of the things that lets us take our user experience and really up it. So we'll see you soon. [MUSIC]