Python Django Framework Full Course - Learning with the Docs

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
What is up, how's it going? This is kazi from  clever programmer calm. What I wanted to cover   in this series is Django. And what I wanted to  cover was like the most commonly referenced Django   documentation, I personally couldn't really find  any videos of people like covering it. So I just   wanted to do that. Because, you know, I see, like  everybody who starts learning Django, this is the   first place you're gonna go to like the docs,  the Django official documentation that shows you   how to, you know, do their getting started guide.  And so I just want to kind of cover that in this   series. And just right now, I just want to kind of  cover the overview, and then we're gonna jump into   actually, the parts of the tutorial, okay, and  you're just gonna follow me along. Alright, so   I'm going to cover this kind of touch on this. So  if you have some experience with it, it will make   a little bit of sense. So designing your models.  So in Django, you can kind of design your database   and models like this, you don't need to type in  raw SQL queries or mess with too many ora, or   MS is just simply classes. So it's literally  like Python and object oriented programming,   and boom, you have stuff populating your database,  which is pretty cool. It also has a built in kind   of API. So it says, you know, as soon as your  models are done, the API is created on the fly,   no code generation necessary. Okay. So here, you  can see that if you create a model, like let's   say that you're creating an app, right, it has  reporters, and your app has articles, you know,   well, what you can just do is just be like, hey,  reported, I'd objects dot all. And they'll tell   you how many reporters are there. For example, if  you made a game app for like, let's say, a street   fighter, and you did fighter dot objects at all,  it might say empty set, which means you didn't   put in any fighters yet, right. But then let's say  you create a fighter or a reporter with the name   john smith, and you save it. Then when you check  objects at all, all of a sudden, you'll say, hey,   reporter john smith actually does exist. So that's  pretty cool. And a really nice way to interface   with it. And then also, you can search for things  in a really easy way to so you can search in your   database with an ID. But you know, a lot of the  times what a more human way to search instead of   an ID is like searching with, what does the name  start with or if the name contains the word myth,   which Smith actually contains, and l match it.  So then what you can do on your front end later   is right now like you're not going to have your  client interface with draft from the code command   line, right? What you can do later is then give  them a front end and interface so then they can   actually type it in the search bar and look up  john smith or typing myth. And they'll still find   john smith. Kind of like when you guys go to like  Shopify stores, or, you know, YouTube and type in   a videos name. And even if you're off, you'll  still find it, it's using this contained search   mechanism, which Django comes built in with.  Another thing I want to touch on is, yeah, so   if you have your model, you can register them in  the admin interface with just a simple line that   says admin dot site dot register. And then that  model votes lets you create the article model,   you can now register it in the admin interface.  So then you can go and point and click an admin   interface, and then delete, or create new articles  or whatnot, right? For example, when you have a   WordPress blog, you know how you have an admin  interface there. And you can create a new blog   post or delete a post or edit, you have full crud  functionality? Well, that's what it mimics by you   just doing this, right. And that's you creating  code from scratch. That's kind of powerful. And   then, obviously, lets you design your URLs,  right, so how do you want your URLs to be,   so for example, you can have it like, you know,  my ab.com slash articles slash the year, followed   by whatever, right, so you can create your own  URL, parameters, and whatever. So this is pretty   standard. But it looks Django lets you do it in  a really clean way, especially with Django 2.0,   their new latest release. Alright, so writing  your views is also pretty easy. You can have   a just like return HTTP response or HTML file you  made. So for example, here you can see, we render   and return like this archive dot html file. So  if you create a HTML file in your templates,   then it's going to be there. Again, if you're  watching this and you're like, I'm a complete   beginner and I have no idea what the heck you're  talking about. Don't worry. If this part is just   not making any sense, skip a little bit ahead to  the part where we jump into the tutorial. This is   just for People who are maybe coming from other  frameworks, and they want to grasp how Python   and Django is working, okay, so you do need some  experience to understand what I'm talking about   here. And then yeah, templates are using, it's,  it's using Django templates, which is kind of like   Jinja. I'll go into this later. So at this point,  like, let's just get started. Alright, so for your   installation, all you really need to do is make  sure you have Python installed. So for myself,   I got Anaconda installed, which is, which is what  I would recommend for you. So if you do Anaconda,   download online, kind of install that. And that's  pretty much all you need to go on. And then   obviously, install Django as well, which I'll show  you in one second, okay. All right, and then you   can go ahead and create a project. So we're going  to just get started from scratch and follow along   with this tutorial. So let's, let's get started.  Okay, so I'm gonna open up my command line here.   So I'm just gonna open up my terminal. If you're  watching this, you can open up your, you know,   CMD on Windows, or, what I recommend installing  is cmd. Er, on your Windows. And, yeah, basically   just see if you have Anaconda installed. And if  you do, and if you type in conda, this distinction   come up, okay. If you don't have Anaconda  installed, that's okay, you can still follow   me along. But what I'm doing here is kind of like  for best practice. So if you want to do it, like   the best practice way, then I recommend that you  get conda installed here, let me just make this a   little bit smaller. Alright, so basically, what I  want to do here is first, check my J. So what I'm   going to do is install my environment with conda.  Okay, so I'm going to do and, again, installing   Anaconda. And like making you understand  everything about virtual environments is outside   the scope of this specific tutorial. So you can  look up stuff, like how to install Anaconda on   Windows, or how to install Anaconda on a Mac.  But I'm just going to go ahead and do conda. Or,   first I'm going to create this project. So let's  see, I'm going to go to my GitHub. Alright, what   I've also done is I have gone into preferences  in my atom. And I have went in under install,   and I've installed terminal, platform meal ID  terminal, and I've installed it. So then the   beauty of that is that when I'm coding, right,  if I'm coding, I can just pop open my terminal,   right in here, and I don't have to leave my adult.  So I will do Django admin, start project my site,   like that, and then go into my site. Okay, and  then I will come over here, and I will open,   I'll go to GitHub, and then I'll go my site, and  then just click that. Okay, that's about it. This   is just so if you guys are following along,  like I don't want you to get confused. Okay,   I'm gonna open up my Chrome. So they're saying  that this is pretty much what it should look like.   And for us, it does look like that, right? We have  my site, and it has all these files inside of it,   and you can see my site, and it has all these  files inside of that. Okay. Um, and then they say,   hey, just go ahead and run Python manage that  py run server. So let's go ahead and give that a   try. So I'm gonna open up my terminal and how I do  that how I open up the little prompt is by doing   Command Shift P. for you on Windows, that might  be a different command, like maybe Ctrl Shift P.   But yeah, for me, that opens it up and then I  just click terminal pops open my terminal. I'm   going to do conda create dash dash name. My site's  Python is equal to 3.6. And I will activate this   environment. Okay, and now I will install Django.  Okay, so if I do PIP freeze, it should show   me that Django and much other stuff is installed  Jango right here, so we're good. Alright, I'm just   gonna make the font bigger so you guys can see it  a lot easier. Okay, so now, we're going to try to   run this Python managed up py run server. And  we will go to this URL on our chrome and see   if it shows us something. Okay, cool. So it says  install works successfully congratulations. And,   believe it or not, this is actually pretty  exciting, because this is the first hint   that your app is actually running. Okay. Now to  this, we're going to add a lot more features to   it and make it really awesome. But right now,  it's being actually served over your localhost,   and it's running, okay. And once we get it to a  point where it's doing a lot of cool stuff, we'll   develop it locally, and then later on, or you can  even do is and put it online, so then anybody in   the world can use your Django app. Let's go back.  And let's take a look at what the tutorial is   telling us to do at this point. So it says that  you should see this stuff, and we do. And then it   says, ignore the warning about unapplied database  migrations for now. We'll deal with the database   shortly. Cool. And it says we have started Django  development server, which is a lightweight web   server written purely in Python. We've included  this with Django, so you can develop things   rapidly without having to deal with configuring  a production server such as paci until you're   ready for production. Cool. All right. And they  say don't use the server in anything resembling   a production environments tended for developing  cool, no problem. All right. And now they want us   to get started on creating the polls, polls app.  Now that your environment a project is set up,   you're set to start doing work. Each application  you write in Django consists of a pure hour of a   Python package that follows a certain convention.  Django comes with a utility that automatically   generates a basic directory structure of  an app, so you can focus on writing code   rather than creating directories. Cool. All right,  projects vs. app. So what's the difference between   a project and an app? Now, the cool thing with  Django is that everything is considered an app.   Okay, so let's say that you create a website that  has a blog that has an e commerce capability. Now,   the blog is considered a so let's say you created  this website with Django, right, the blog would be   considered a Django app, and your ecommerce store  would actually be considered a different Django   app. Okay. So there'll be two different apps that  your web application is comprised of. That's how   Jango handles the logic. So basically, it's one  project that has multiple apps inside of it. Okay,   that's pretty much what they're saying here.  Okay, so an app is a web application that does   something. Okay. So a web blog system, a database  of public records are simple pull up a project   is a collection of configuration apps for a  particular website. A project can contain multiple   apps, an app can be in multiple projects. So you  can have one app that you build for one project,   and you can actually have it in different projects  that you're doing, which is really cool. It's like   plug and chug. Your apps can live anywhere on your  Python path. In this tutorial, we will create our   poll app right next year, manage that py file,  so that it can be imported as its own top level   module rather than a sub module of my site. Okay.  To create your app, make sure you're in the same   directory as manage.py and type this command.  Okay, so now this command Python manage that   py startup polls, we're going to do that, okay.  So, we're going to break our server with Ctrl C.   case I did that I'm going to hit LS, and it looks  like I'm at the same level as my manage.py file,   and if I had pwd, pwd will show me where I'm at.  And now, I'm going to do Python managed.py start   app. And the app is called polls, I believe  just let's just double check. Okay, so now our   polls app is created. And let's just take a look  inside of polls. Polls. Okay. So inside of polls,   you can see that we have a bunch of Oh, actually,  let's look right over here. It's easier that way.   So Paul's comes with migrations in net dot p y,  admin apps, models, tests, views. There's a lot   of things That polls comes up with automatically,  which is really nice. But a lot of this stuff is,   you know, just kind of empty. The main things  that you're going to be working with is models   and views, okay, that's, that's the thing you're  going to be working with like all the time,   when you're developing apps for yourself later,  you're also going to be playing around quite,   you're going to be doing adding stuff to test  to make sure you can test your app as you're   building it. And then migrations is going to  be important, because it's going to kind of let   you time travel in your database. So when we keep  making changes to your database, with migrations,   you can like roll forward to a certain time.  But let's say like things get really messed up,   you can roll back to a previous point in time. All  right. So the disk directory structure will how's   the poll application. So this is the directory  structure that we actually saw, okay. And now they   want us to write our first view of view is what  lets you go to a specific URL, and then it returns   some kind of response. Okay. So for example,  so Django works off of something called MVT,   which is called Model View templates, your  normal apps, you know, node.js, or whatever those   frameworks work off of MVC model view controller.  So to give you an example of this in real life, is   when you go to google.com, slash, you know, when  you go to google.com, and you type in like cats,   right? Or let's say you go to google.com. And you  type in whatever the response that comes to you,   right, that maps to the current URL you're at. So  how does Google know to show you the Google logo   and the Google homepage when you go to google.com?  Right. So google.com, when you type it in,   it sees what your current URL path is, then it  goes into the Google code base. And then it finds   this HTML file that says, if somebody goes to this  path that says google.com, then show them this   HTML page that has Google's image on it, followed  by a search bar, and then shows you that, okay,   so it returns a response, you request something  and it returns a response. If you go to apple.com,   slash, watches, or watch, I don't know if that's  actually a real Apple URL, but like, let's just   say you're trying to get an Apple Watch. Okay? So  if you go to apple.com, slash watch, how would it   return to you all of their watches, right? So  what actually happens is apple.com slash watch   will match that path in their code base. And then  it'll see if there is a HTML file that corresponds   to it. And it'll show you that HTML file, okay,  as a response. And that's essentially what we're   going to do. Well, we're going to have a very  basic version of it. So we're going to go in our   poll slash views that py. So I'm in my polls, and  I'm going to go in my views that py. So when they   say it, like this poll slash views that py, that's  what they mean. And in here, I'm going to say from   Django dot HTTP import HTTP response. Right. And  then I'm going to go here, I'll say define index   requests, take in a request, and then return  an HTTP response. And I will say, Hello, world,   your ad. Let's do it with double quotes, because,  hello, world, you're at the polls index, right.   And then they have a little comma here, this  doesn't matter so much, there's just a string.   So it doesn't matter what you do. Make sure you  always save what you're doing, because otherwise   it won't take any effect. So make sure you do  Ctrl S or Command S the whole time. So I just   created this, but the thing is that it's not going  to show up. So now what I need to do is like, tell   my app that when somebody goes to the home page,  yo, you got to show this exact this thing right   here. Okay. This is the simplest view possible  in Django to call the view, we need to map it   to a URL and for this, we need a URL con for a URL  configuration. To create a URL confit in the polls   directory, create a file called URLs dot p y. Your  app directory should now look like this. So now   notice there's a URLs dot p y here, which was not  there before. Okay, so we're going to go in our   polls, right click here and create a new file and  call it urls.pi. Okay, And now in our URLs, r p y,   we got to add from Django dot URLs, import path  from Django dot URLs, import path. And then we're   going to do from import views. And then we're  going to do URL patterns. So what you want to do   is try not to indent, but use four spaces instead.  Okay? 1234 if it doesn't automatically bring you   to the right place. All right. And I want to  do pass. So if somebody goes to the empty path,   then I want you to go into our views file and use  the index function. And we're going to call give   it a name index. Okay? So what does this mean?  If somebody goes to, let's say, your website is   called john, calm, right? somebody goes to john  calm, followed by nothing else. So not like john   calm slash article slash blog, none of that is  just john calm your homepage. What happens? Well,   then we say, going to the views file and  run the index function. So in under views,   this is index function, I'll run that. We're  naming it index. So then later, if we want to,   from our templates, or HTML, if you want to refer  to this specific URL path, we can just call it by   index, no, reference it. Okay, the next step is  to point the route URL configuration at the polls,   that URLs module. Okay, so you're all content, and  we got to point it to this. So Alright, in my site   slash urls.pi, add an import for Django dot URLs  include and insert include in the URL patterns   list. So you have this. So we're going to go in  our my site slash URLs right here. And in here,   we're going to add this line, okay? Because we're  saying if somebody goes to the path polls, then   run the polls, URLs. Okay. So from Django contrib,  import admin from Django, import from Django dot   URLs, import include, comma path, okay. And that's  because we're gonna do the include thing right   now, just like that. Okay, and then hit save.  So if somebody types in john comm slash polls,   now we'll say, hey, try to match this pattern by  going to the polls, our URLs file. Well, where's   that that's in the polls app. And it's this file  right here. So then it'll go to this file, and   then it'll match this first guy, and they'll say,  Okay, I'm going to run the home function, okay. So   anytime somebody goes, anything, polls will refer  to that file, that URLs file. Alright, the, this   is what they're basically saying here. The include  function allows referencing other URL cons,   whenever genuine counters include, it chops off  whatever part of the URL match up to that point,   and sends the remaining string to the included  URL con for further processing. The idea behind   include is to make it easy to plug and play URLs.  Since poles are in their own URL client, they can   be placed under or any path and that will still  work. Okay, you have now wired. So now it says,   You should always include, you should always use  include when you include other URL patterns. Okay.   And now it says you have now wired an index view  into the urine. Let's verify it's working. Run the   following command. Okay, so now we're going to run  this thing. And we'll go to our localhost or this   HTTP is port over here. And hit run. And now we  are getting an error. Oh, yes. Basically, you have   to do slash polls, okay, of course. Because it's  not a home page thing that we've added to because   I just saw this and I was like, oh, homepage, but  it's because we got to go to the polls path. Okay.   So everything after so it's like, when you put  this online, when you put this app online, right,   it will essentially be like, your app comm slash  polls, is where you'll have to go to and then I'll   know what to do. Okay, so let's say you're at the  polls index. And that's exactly what we see. Now.   Cool. Go to this in your browser, you should  see the text which you define in the index. The   path function is Pat is passed four arguments to  require In view and to optional, at this point,   it's worth reviewing what these arguments are  for. Alright, so we're not going to go into   too much detail is going to be like still casual,  and we're gonna keep moving forward. We're gonna   do part two of the official Django tutorial, we  have already done quite a bit of stuff, right,   we've gotten our local servers started. But what  we want to do now is in this video, we're gonna   actually cover our admin interface, and we're  gonna actually start playing around with it.   So it's gonna be pretty exciting. I hope you're  willing and excited to see how that works. Okay,   and we're going to go through this one a little  bit faster. So Okay, so first thing we want to   do is like, look at the database setup, which you  can, frankly ignore if you're new. But later on,   like, this is something that you should read.  But for now, we're only going to focus on this   command that says Python managed up, py migrate.  Okay, so this is a complete continuation from the   last video, okay, so make sure you're caught  up on everything from part one, I'm gonna open   up Adam. And I'm going to break out of this by  doing Ctrl. C, and I will do Python managed up,   py migrate, and it should give you a bunch of  okays. And what that did is created these tables   that weren't created before, okay. So they're all  created, like stuff with usernames and emails, and   permissions and all the stuff that it has to do  on the back end. Okay. All right. And from here,   we're going to go on, and we're going to try to  now create models. Alright, so we'll define your   models, essentially, your database layout with  some additional metadata. How Django models work   is their philosophy follows the DRI principle,  which stands for do not repeat yourself,   which is a really common, commonly used acronym  in the programming world. And it emphasizes using   logic that helps you never really repeat yourself,  right. So for example, just to give you a simple   example, imagine if you had to print out a letter  or print out the word Boom, 100 times, you could   keep writing print, boom, print, boom, print,  boom. Or you could do it in the dry way, which   is write a for loop that prints it out 100 times,  okay? So that way, it allows you to stop yourself   from repeating, and just helps you do it at once.  Now, when you start abstracting it and taking it   to a higher level, that might mean taking your  code from basic, basic code, and modularizing it   into a function or into a class or into a package,  things of that nature, okay. And that's the same   philosophy Jango goes off on so instead of like,  repeating yourself over and over again, it lets   you create a class, which then creates models out  of and handles a lot of that stuff for you. Okay,   so we're going to create this these models, okay,  and basically what we're going to be working on in   our simple poll app, we're going to create two  models question and a choice. A question as a   question and a publication dates, almost imagine  like a spreadsheet. Let's say you create a new   sheet in the spreadsheet and you call the sheet  question. You have column one that says question   tax, column two that has a publication date. So  question tax on your first row might be, what the   hell is going on? And the publication date may be  like, February, whatever. And your next question   might be like, when is causing you going to make  the next piece of content, stop making all these   crazy videos where he's outside talking to the  camera, and then your publication date next to it,   right? So that's how I want you to picture when  we create these models. Alright, with that said,   let's move on. Our choice is going to be its own  spreadsheet or its own sheet. Okay. And basically,   what it does is a choice has two fields, the text  of the choice and a vote Tally. Okay. So the chat   text and the vote Tally. And then the question  that you get to choose is actually referenced   from the question model. Okay, so let's actually  now write this code out. So let's go to our polls.   And I'm just going to copy paste it, I recommend  that you actually write it out because it's really   helpful exercise for you. But just for a time, I'm  going to go through it faster, we're going to put   it I'm going to paste it right here. Okay,  I'm going to save it. Alright. Now we have to   activate our models. Okay, so I'm going to go into  my settings, my site slash settings. And inside of   here, I want to tell Django that we actually have  this app installed. Okay. So what I want to do is   polls dot apps dot, I think it's polls config like  that, okay, and make sure to put a comma after   it because after all it is a list with 1234567  elements. Okay, so now Django knows to include   the polls app, let's run another command. So up  until now Django had no idea what this thing that   you created this polls app. But now that you went  in my site and added this under settings and added   to your installed apps, now it knows that it's  actually there. Okay. It's the equivalent of kind   of like, let's say you downloaded an app on your  Mac or your windows, but you never installed it,   right, like downloaded a game, but you never  installed it's kind of like that. So we just   installed it by doing this. Okay, and now what we  want to do is let's run another command, Python,   manage that py make migrations polls, okay? So I'm  going to come in to my command line. And again,   to activate your virtual environment, you'll  do source activate, followed by the name of   your virtual environment. And to deactivate your  virtual environment, you will do source deactivate   if you're on a Mac, if you're on Windows, and all  you need to do is activate, followed by the name   of your virtual environment. So in this case,  it will be my site. Okay, so since I'm already   activated on my virtual environment, I'm just  going to do Python manage that py make migrations,   poles. And now you see that it says Create model  choice, create model question, add field question   to choice, okay. All right. By running make  migrations, you're telling Django that you've made   some changes to your models, in this case, you've  made new ones, and that you'd like to change this   to be stored as a migration. Cool. And this is  effectively what the sequel will look like for   this. So this is not something you have to worry  about. If you're a beginner, and you don't even   know what SQL is totally fine. But if you have  a little bit of experience, check it out. What's   really cool is like a bunch of this code that you  would normally add, like generally anything to do   with databases requires you to know SQL or write  SQL, okay, SQL. And for you to write raw SQL,   it looks pretty complicated, right? Like, for  example, if you go here, there's a lot going on.   If you write SQL every day may not be that big of  a deal, but it's a lot going on. Whereas Django,   it's automatically generating all this code for  you. And you don't actually even have to worry   about it, I just showed it to you. So you can see  what it actually looks like, on the back end. So   that's what they're showing here. And we're not  just gonna, we're not going to worry about that.   And since we made the migrations, we're going  to commit those migrations to our database by   doing Python managed.pi and typing in migrate.  Okay, so now it says applying polls initial,   and it says, Okay, if I go to my migrations, I  can also see this specific migration that I made,   okay, and I can read this migration whenever I  want. Do not mess around with this file too much   unless you know exactly what you're doing. Okay,  cool. And now we're going to play with the API.   Another thing about migrations, when you get  a little bit more advanced, it allows you to   update your database without ever losing track  of it. So flask has kind of a weird migration   thing going on, whereas Django kind of comes with  it. And so it's databases a lot easier to play   around with. Like it says, migrations are very  powerful that you choose your models over time,   as you develop your project without the need  to delete your database or tables and make new   ones. That's generally what you have to do. If  you're working with, you know, like just kind of   working from scratch. It specializes in upgrading  your database live without losing data. So again,   this is going to be really powerful and helpful as  you get more advanced. And as you do more things   with models. So now let's play around with the  API that actually Django gives to us for free.   Alright, so we don't actually have to write it, it  just kind of comes with it. So I'm going to go and   instead of just typing in Python, I'm going to do  Python manage.py shell, okay. And here, I will do   from polls on models, import question, comma,  choice. And then now we can play around with   it. So since we don't have any questions in our  system yet, when we actually look up questions,   and the objects for it, it should show us  empty, right, because we didn't create any   thing from in the question model. Guess if I do  this at all. It should show us none. And that's   exactly what is showing us like, hey, the query  set is actually empty. Now what we want to do is   create a new question. All right. Django expects  a time date use time. So now instead of this and   it will do the right thing. Okay, so we're gonna  go from Django dot utils import timezone. Okay.   And what does our question take? Remember, if we  look in our questions model, it takes two things.   It takes a question tax and a publication date.  And that's what we want to give it to create a   new question object, okay. So pretty much typed  that in what is it saying? It's saying, Hey,   I'm creating a question object. This question.  Class essentially takes in a few things, question   tax and publication date, and I'm using keyword  arguments. So I'm putting question underscore   text equals. So for the question text, it takes in  a car field. So let's go actually here in models,   and you can see that it takes in a character field  right here. And that's why I'm actually passing it   in as a string. And then publication date takes  in date time field, and that's why I'm passing   in the timezone dot now, object, okay. And just  gonna hit enter here, and now, Q is created. So   I should be able to do something like, well, let's  follow along with their documentation is saying,   but if we actually do this now, right question  that objects dot all let's see if it shows us. So   that's because we haven't saved this yet. So once  we save it, it's going to show up in our as one   of our created objects for a question. So let's  follow along. So now it says, save the object into   the database, you have to call save explicitly.  So we're going to do that I'm going to say q dot   save. And let's try it again. And now look, it  shows us that there is indeed one question and   that even has a number an extra one. Okay, but  it's not very helpful, because it's not showing   us what that question is. Or it's not giving us  a very easily readable name when we actually use   this API. So I'll show you guys how to overcome  that, too. Alright, so now it has an ID if you do   q.id, it'll show you its ID. It says access model  field values via Python attributes. So I could   do q question, tax. So that question text right  there. And they'll show us like, what's new, and I   can do q dot pub location, date. And they'll show  me the date as a date time object 2018 two, which   is February 19. And let's go down here. And we can  even change the values by changing the attributes   and then calling save on it. Okay. So for example,  before we had the question, that's what's new,   we can now save that question as What's up, okay.  So for example, I can do cute question, underscore   text is equal to what's up kids at home. And I can  do q dot save. And now if I do Q, question, text,   you'll see that it actually says what's up, right?  displays all the questions in the database. So now   if I again, do this, which you've seen, it'll  show me all of the questions right. Now we only   have one question. Okay. So if I wanted to add  multiple questions, I could do that. You know,   let's say that we add q2. And then I do q three,  and then I go right over here. Instead of saying   what's new, say what's poppin that, hit Enter. And  now if I do question dot objects, dot all you can   see that it shows me Oh, sorry, I have to save q2  dot save q three dot save. And now if I do this,   you'll see that it shows me I've one question  two questions, three questions. And I can even   say for a question and question dot objects  dot all I can loop through it, print question,   dot question underscore text like that. And if I  run that, it'll loop through all of these and then   they'll print out the question text, okay, so you  can do it. This is just like playing around with   xAPI and kind of getting comfortable with it.  Okay, and it's close. Wait a minute. Question   isn't a helpful representation. You know this  object? So let's fix that by editing the question   model in the thing. So that's what I was talking  about, right? Like, they're saying it in their   technical terms. Basically what they're saying  is like, hey, look, this looks ugly as hell,   and doesn't give us any information like what  this is about. So let's make it into something   that a human can read and be like, Okay, I  get what this question is, and it's readable,   right? So that's what we want to do. All  we need to do is add a string method. Okay,   so we're going to add string representation to  it, you'll see what I mean, in just a second. So   right now just shows us like, blob like whatever,  right? Well, we're going to do is under the class   question, we're going to add string method like  that. Okay. And it's going to take in self, and   then we're going to say return self dot question  underscore text, like that. Okay. So instead of   showing us this, wouldn't it be nicer if it showed  us that question? Because that's a much easier way   of identifying what that question is, when you're  just looking at the list. It's just more readable   that way, okay. And we're going to do the same  thing with choice, we're just going to go here,   create a function, or create a method, because  we're inside of a class. And I also self and I'm   going to say return. So self dot, what do I want  to do here? choice underscore tax. All right. And   I don't think I have to here. Let's try it. Okay,  cool. So now, it's important to add string methods   to your models, not only for your convenience, own  convenience when dealing with interactive prom,   but also because object representations are used  throughout Django is automatically generated   admin. So later, when we go and I show you the  admin, this is actually going to be helpful there.   Because then when we're reading these names, the  admin is going to be using it. All the however,   we're showing it in the console right now is going  to be showing it on our admin interface, right. So   like, imagine, if you create an app, and you give  it to your client, where it's like a blogging app,   right, or if it's an e commerce app, you don't  want them to go to the store. And when they're   trying to differentiate between items, it just  says item one, item two, item three, item four,   it'd be much nicer if it says, like bicycle, or  watch or iPhone x or whatever they're selling,   right? It'll be easier for them to identify.  That's essentially what we're doing right   here. Note that these are normal Python methods,  let's add a custom method just for demonstration.   So they're adding a new method here. So we're  going to do that I'm going to go into my models,   and we will import date time at the top. And  then we're also going to import timezone. Oops,   right underneath this guy. And we will add  this method under a question. Okay. Okay,   so was published recently is a method in the  question class, so you can do like q dance was   published recently. And it will tell you what it's  going to do is going to basically tell you true or   false, okay, so I think what it's checking for is  like if it was published within one day, or later   than 24 hours, let's see what they say. No, the  addition of import and to and from Django, import   timezone. to reference Python standard date time  module on Django is timezone related utilities,   respectively. save these changes and start a new  Python interactive shell by running Python managed   up py shell again. Now, because we didn't make any  changes to the models, we just added new methods,   we don't have to migrate this to our database, all  we need to do just like exit out of this shell and   just like, come to it again, I'm gonna do exit  open closed paren. And I'm just gonna do Python   manage that py shell again. And then let's see  if we can get that command from poles or models.   So basically, from this file polls dot models,  I'm importing this class question and this model   choice model, both are models, classes, whatever.  And make sure our string our addition is working.   Okay, so now we're going to try to do the same  thing except this time, it's not going to show   us question whatever is gonna actually show us the  text of each question. So there you go. What's up,   what's new, what's poppin Okay, much easier for  To see this Okay, so again think of it like if   you had a fighter database instead of it saying  fighter one fighter to fighter three, it show it   to as like can write you and like say got Django  provides a rich database lookup API is entirely   driven by keyword arguments. Okay, so you can do  something like, hey, I want you to filter by where   the ID is one. So give me that specific question  only, or I can say filter by 82. And it'll give   me the question that has ID of two, okay? Or I can  filter by question tax that says new inside of it,   or what's new inside of it? Just like it's showing  me here, like, if so let's try this one. Okay. So   question text starts with what? Okay, so let's  see. So far, all of these start with a what? So   it's going to show us all three. But what if I do  instead of starts with I say contains? And I say,   often? Okay, there's only one question  that contains that, okay, then later,   we can provide a front end to our client where  you can like, in the search bar, type it in,   but on the back end, we're using this contains  method to find the exact thing that you need,   and then return it as a response from our HTML  file. Get the question that was published this   year. Okay. So let's get the question as published  this year, we're gonna do this. We're gonna say   current year is timezone. Now that year, so  that's going to get basically 2018. Right? If   I do current year, it'll say 2018. And question  that objects I get, where the publication date,   year is the current year. Okay. So let's do that.  Get returned more than one question or turn three.   So because we have multiple questions, instead of  one, RS is going to be different than theirs very   slightly. Okay. So for ours, since it matches  all of them and gets like Yo, what's going on,   I'm matching all of them. So but nothing to worry  about, it's still working for us. If you request   an ID that doesn't doesn't exist, it will raise  an exception. So for us, we do have ID two, so   it won't raise an exception. But like, let's say  that we try to find something with an ID of four,   or five. Sorry, we have to do dot get is going to  raise an exception, okay. Also, for this, let's   try. So what would happen if instead of dot get  we use filter? Would we get an error? Or would we   get something in return, we would get something in  return, which is like, all of these that match it.   Okay? So the difference between filter is like,  return everything that matches and get is like   get one. And if more than one match, then like  throwing an error or something like that. Okay,   so look up by a primary key is the most common use  case. So Django provides a shortcut for a primary   key lookups a falling question. The following is  identical to questions that objects dot get ID,   so PK, which is a primary key. Okay, so every  model will have a primary key. So for example,   question we'll have a primary key choice, we'll  have a primary Kanda think about this is like,   let's say you have a database with people in it  right? or employee names. But what if you have two   john smith employees, right out of 100? employees?  Or what if you have two Apple watches in your   ecommerce store that you're selling, that are the  same name? Or the two people that have the same   name? How are you going to differentiate? What  if they have the same email address or whatever,   right? So you need one thing that's always always  always always unique. So if you can't rely on   their first name, last name, or email address,  or whatever else, one thing you can always rely   on is a primary key. It could be an automatically  generated key from Python and could be like random   words or whatever, right? Django will handle  the primary keys for you Everything will have   a primary key even if it doesn't show it to you  on the back end. This way, you can always find,   you know, the unique way of referring to  something, okay. All right. So let's go   here saying that makes sure our custom method  worked. So it says cute dogs that get PK one,   okay, so basically what I'm going to do is go  here and say hey, Get me the object where the   primary key is one and save it as Q. And now I'm  going to ask if q was published recently. Okay,   and it says true. Okay, cool. So that's the result  we got. Give the question question a couple of   choices. The create call constructs a new choice  object does insert statement as the choices   set available choice and returns a new choice  object. Django creates a set to hold other side   of foreign key relation questions for which can  be accessed via the API. Alright, so we're gonna   do this guy again. If you haven't done so already,  display any choices from the related objects set,   so we don't have any choices so far. Okay. We're  right now basically voting for questions kind of   like you can upvote comments on YouTube. So  now we're going to create three choices. So   cue that choice that create. So we're going to  take a question, which is our first question,   which was like, what's up? And we're going to  create choice taxes equal to not much with zero   votes. Okay, and you can see choice has a field  called votes, and then it has choice tax. So our   first answer to that question, what's up is not  much. But we're saying like, Look, it only has   zero votes. Okay. Okay. And now we're going  to create another choice, but called the sky,   what's up the sky? I mean, I guess that's kind of  funny. I say the ceiling. And then here's another   one that is, and we're going to store this one  actually. As see, Oh, okay. There we go. Okay,   so now choice objects have API access to their  related question objects, because then if I do see   that question. So even though I've created this  model from choice, you know, you'd be looking,   I be like, hey, how does it have access to the  specific question like, how did it access this   field? Here's how I did it. Because we're saying,  in this question, go to the foreign key, and the   foreign key is this model over here. When I do  choice question, it'll go and get the question   from up there. That's essentially what it's doing.  Okay. So that's what, when I do see that question,   that's what's happening. It's referencing and  getting me back this object. Okay. And vice versa.   So you can also reference from question you could  reference choice. Question objects had access to   choice objects, okay. So they both have access to  each other kind of like, you can have a book and,   you know, like, who was the author of this book.  So that relation goes to the author. And then   you can say, like, this author has which books  and it can relate back to the books. Alright,   so now we're going to see how many choices we  have. And so we have not much is one choice,   the other one we have is the sky. And then the  other choice that we have is just hacking again,   all of these have zero votes, as we see right  here. And we're gonna say q dot choice underscore   set counts. So this is just a count that there  are actually three choices. The API automatically   follows relationships as far as you need us double  underscores to separate relationships. This works   as many levels deep as you want. There's no  limit, find all choices for any questions whose   publication date is in this year, we're using  the current year variable we created above,   okay. So I can say choice that objects or  filter, question. Double underscore means like,   you are kind of going backwards. So we're saying  question, and then we're going publication date.   Okay, so actually, we're going this question  here, and then we're going to publication date,   and then checking the year getting the year of  that publication date. Okay. So let's try that   right over here. So it's going to get us all the  way questions that are from this current year.   So it should get us all three of these. Let's  delete one of the choices use delete for that.   So now what I can say is, I can get the question  that starts with just hacking. Right? And how do   I do that? I say cue that choice set da filter by  where choice text starts with just hacking. Okay,   so it's only going to get one question that  has just hacking in there. And if I do see,   I'll show you which one it is. And now to  deleted all I do is see dot delete. Again,   I'm copy pasting, copying and pasting for time,  purposes, saving time, but for yourself, like   take the time to actually write all of this out,  because it's very, very helpful for you. So now   that I deleted, it showed me that it's deleted.  And if we actually check again, right, it'll only   show us these two choices right here. Okay. Now,  we're going to get into a pretty exciting part,   which is introducing the Django admin and we're  actually going to just touch on it a little   bit. And let's get started. This is a super cool  part. philosophies of generating admin sites for   your staff or clients to add, change and delete  content is tedious work that doesn't require much   creativity, okay? is usually like a pretty rinse  and repeat process. It's frustrating, it's boring.   You can make mistakes, it takes a lot of time, and  development, and which means like, it'll cost your   client a lot. And it slows down your development  speed. For that reason, Django entirely automates   creation of admin interfaces for models. Okay,  so let's check it out. The admin isn't intended   intended to be used by site visitors, it's for  site managers. Okay. So now we're going to create   an admin user, I'm going to do Python, manage  that py create. So we're going to exit out of this   and do Python, manage that py, create super user.  And I'll leave this blank, I'll use this email.   And even though it's not gonna show you anything  here, it's still typing in your password. So don't   worry about that. Okay, so you can put in whatever  as your email, whatever is your username. And now   the final step is to answer enter your password  I have. And now it says start the development   server. So we're going to do just that. I'm going  to start the development server, we're going to go   to Chrome, we're going to go to our local app on  127 dot 0.01, colon 8000 port, instead of polls,   I'm actually going to go to admin. And when I go  to admin, look, it brought up this nice interface   that you and I did not make, we didn't make this  beautiful looking form, where when you hover over   log in it, like turns dark and looks good. And  we didn't add functionality that add security,   right? We didn't add this thing where passwords  automatically looks like dots so nobody can see   it. All of this keep in mind is just automatically  generated. When I click login, boom, here's the   administrator interface. Okay, so as the admin,  you can change your password, you can log out,   you can check what who are the users. So here's  one user, you can like, go into this user and like   delete this user, or change the permissions of  this user, right? So you can go in and like boom,   it's not a super user anymore, or is not a staff  anymore. It's not active anymore. Or you can go in   here and like change all kinds of permissions,  like can delete choice can add a question but   cannot like delete a question can change a  session, but cannot delete a content type,   you know, you can get like as specific with it  as you want. And this is just for the model that   we have registered new users. But imagine later  when if we register our choice model and whatever,   those will all show up right over here. And any  recent actions that you do actually show up on the   right hand side. So imagine like somebody deleted  something, you're like, what the hell happened,   like, one part of our app or this website is  now broken? Well, if you go into recent actions,   you'll see what took place and exactly who did  it and who to hold responsible for that. I think   that's pretty cool. Right and it comes built in  right out of the gate. That's one of the reasons   why Django is such a powerful tool. And it fosters  productivity and effectiveness. I believe over any   other framework, right. And their tagline, which  is awesome. It's for Django is for perfectionist   with deadlines. That's what I believe in to  like, if I have to put a project together,   and I'm doing something solo, I'm going  Django, all day baby. But you know,   if you're working on some long term project, you  know, you're going to be doing for a long time,   and nothing else really matters, then yeah, you  can choose whatever you want. But I like speed,   I like productivity, I like to take my ideas from  my head and launch them online fast. Alright,   with that said, let's go back and see what  they're saying. So we go to our admin,   enter the admin site. And now it says, make  the poll app modifiable in the admin. How   do we do that? We're going to take these three  lines of code. So I'm going to go into my polls   slash admin. And this line is already added.  So I'm not going to add it in from dot models,   import question. Okay. So basically, what I'm  saying is from this directory, get the models,   so right here. And import the class question from  the models. Okay, so import the question model.   And then I'm going to say, registered that model  inside of admin. So check out what happens. Okay,   this is super, super cool. Check it out. I'm  gonna hit save. And let's go back to our app.   And let's hit refresh. And look at that. It's  here. That questions model is the one we made,   it shows under polls, questions, and you can see  all of those questions. What's poppin? What's new,   you can go in and you can change the text. So I  can change it to like, what's cracking? Right,   I can hit save. And now it's changed. And if I  go to my, if I start Python managed up py shell.   From polls, dot models, import question. Question  objects. All right, look, it says what's cracking.   So what we actually changed from the GUI interface  with our mouse, and our keyboard is now showing up   in our database in our local database, SQL lite  database actually being stored on our computer,   this database is not online yet. So pretty freakin  cool, right? How quickly and how effectively   works. So I'm going to exit out of this, I'm going  to run my server again. And we're going to go back   to the app refresh. Cool. And like, let's see  what they're saying. Now that we have registered   question, Django knows that it should be displayed  on the admin index page. And it is right and I   showed it to you. And we went inside of it. And  we saw question tax and we saw date published   and we can actually change the date published  and everything. Now things to note here, the   form is automatically generated from the question  model. So this form is automatically generated,   we didn't generate anything, the different model  field types, date, time field and car field. So   remember, we had one of the models as a date  time field, and the other one is car field.   And you can see where it says date published  load Date field, right? And for question,   text is just a straight up character field,  or what you know, in Python to be as a string.   These correspond to the appropriate HTML input  widget, each type of field knows how to display   itself in the Django admin. Pretty cool. Each day  time field gets free JavaScript shortcuts, whoo,   free JavaScript shortcuts. That's awesome, too.  Normally, you'd have to write JavaScript for all   this stuff, but like, look at this, okay, so let's  say I go to what's cracking, and I click here,   boom, look at this beautiful date time picker  thing opens up, and you could pick today, or you   could pick another date, and like automatically  pick it and you could pick the time. And that's   cool. This is this is something you'd have to  write a lot of manual JavaScript for, that's   automatically written for you. Dates get it today,  shortcut and calendar pop up and times get a now   shortcut and convenient pop up that lists commonly  entered times. The bottom part of the page gives   you a couple of options, right? So save saves  changes and returns the change list page for this   type of object. So you can do save, or you can do  save and continue editing. So continue editing the   same page or you can just save and add another  add a new question. Right. Or you can do delete,   which displays a delete confirmation page. So  check this out, okay? Normally when you hit,   you have to add all this functionality. Plus  when you hit delete, you have to then remember to   add a confirmation thing to it. And they have it  automatically. So if I hit delete, it'll be like,   are you sure you want to delete the question?  what's cracking? All of the following related   items will be deleted. Questions, one. So only one  question and objects. What's cracking? You can say   yes, I'm sure or no, take me back. Now notice,  it's showing the question is what's cracking?   That's because of your string method that you  added your str method. If you did not have that,   it would not show like what's cracking, it was  show like question one. And you just have to use   your memory to remember that. I'm going to say  no, take me back, and it'll take me back. Okay.   Cool. Let's go back. Let's see what they're saying  here. And then if the value of the date published   doesn't match the time you create it, it probably  means you forgot to set the time. We can also set   the current timezone, right. So that's not a big  deal. If I go in history here, it says I changed   at 3am. It's not 3am right now. So that means  like, I need to go inside of my settings and   in my timezone and change what my timezone is.  So for example, I think there's like, America   slash Los Angeles, something like that. Oh,  actually work sweet. for yourself, just look up   like timezone Django timezone settings, and then  find yours and put that in for me, I put this in,   and it fixed my time instantly, right. Okay, so  yeah, I essentially that's it for part two. We're   gonna jump into part three. And we're gonna get  started. So if you haven't already open up, Adam,   go to where you created your mind site project,  right? For me, it was in GitHub, my site,   I'm going to click Open. And I'm going to say,  whatever open and recover state. Cool. And here   it is. And then if I do command, shift P and type  in Terminal, my terminal pops up. But uh, bam,   and also make sure to do source activate my site.  And we are good. Okay, so writing your first   Django app, part three. So what they're talking  about here, is they're saying, okay, like, Look,   you have everything in Jango is essentially  called a view. Okay? So for example, if you   have a blog homepage, that's a view, if you have  the ability to comment, like a comment action,   right? That's considered a view. If you click  on a blog post, and it shows you the details we   refer to that is a detail page, but that's still  part of the view. That's essentially what they're   saying right over here. Another example of this  is like, let's say I take you to Instagram. So   let's say I click on clever kasi, right? This is  essentially for Instagram. And let me just plug   my Instagram here to go follow me if you aren't  already. Because awesome. And if you go here,   right, like, Look, this is the home page for all  my posts, okay, this would be considered the home   page view. If I click into it, that's considered  a detail view, because it's only showing that one   particular post, okay, if I click here, that's  a comment action, which is, you know, you can   work that into the views. So just wanted to show  you that. So you understand where all of this is   coming from. Now, we come over here, and that's  now they're saying that in our poll application,   we're essentially going to have an index page in  our views. So this is going to display the latest   few questions. We're going to have a detail page,  which is going to display a tax with no results,   but with a form to vote. So when you click so  like, you come in you a bunch of questions, you   click on a question, and then boom, it has like  ability to vote it up and down. Okay, I assume.   And we have a question results page. So it's going  to display the result for a particular question.   How did that question do? How many votes it got?  And then we have vote action. So handles voting   for a particular choice in a particular question.  Okay, cool. All right. So now, we kind of know   that we're going to be creating like these things.  Okay. We're going to be creating an index homepage   detail and results. And also what they're saying  over on this part. Is it saying like, Hey, man,   have you ever seen really ugly URLs like this?  Well, don't worry, because in Django, you can   make them really beautiful. So you can Have them  like this instead, like john smith comm slash news   archives slash 2018 slash two or slash February,  whatever. And you can make them look really nice.   How does it work? It works off of URL concepts or  your current URL configuration mapping, okay? So   you map URL patterns to views. So somebody goes  to this URL, it knows which view to run. Alright,   so now we're going to write more views. Okay,  so we're going to write these guys here. Again,   I'm just going to copy it and talk about it for  you, I encourage you to type it all out and walk   through it. Okay, I'm just going to highlight the  main parts, I'm going to go in my poll slash views   that p y. So in polls, I'm going to go inside  of views are actually we're going to leave the   index for now. paste it here. Okay. So now we  got detail, we got results, and we got vote. Did   everything always takes in a request object? Okay,  a request is passed whenever you do anything. I'm   not going to touch on too much right now. But this  is a first parameter you kind of always put in.   And then as your second parameter, we're putting  in the specific question ID this way, we can look   up that particular question from the database.  So let's say you wanted to look up a blog post,   right? So you have multiple blog posts, you want  to be able to look up a specific one? Well, we're   going to use ID for that. And in this case, our  ID is our primary key. And that will allow us to   look up that unique thing, or in Instagrams case,  it allowed us to look up that unique post. Okay,   cool. Now, what we want to do is wire these  new views into the polls dot URLs module,   but adding the following path calls, okay, so  that's what it's showing here. I'm going to call,   I'm going to copy this and I'm going to paste it  into our polls slash URLs up here. Go slash URLs   and paste it here. Alright, so what does this  mean? If you just go to slash polls, right,   so john smith comm slash polls, it's going to run  this thing is going to match the empty pattern   after polls. And then it's going to run the views  dot index function, okay? If you go to polls,   slash, if you want to go to something like  polls, slash five, or Instagram post slash,   whatever your post is, right? If you want to  build to do that, you want a pattern that can   match that, okay. So if I put in 20, it shouldn't  break. If I put in eight, it shouldn't break,   it should always be matched. And so how we can  do that is we basically do this thing with angle   brackets and int, colon, question underscore  ID. And this can dynamically match whatever   pattern you put in. And another beautiful  thing, you guys, usually for URL mapping,   you have to deal with ugly regular expressions,  except for the latest Django, you don't have to   worry about regular expressions anymore. So  for example, let's say you wanted to match   this particular pattern. Well, you can put this  in, and if somebody puts in a five here, right,   they'll automatically know that it's an integer  and work. If they put in something else, it might   freak out. Okay? So it's really smart. And then  it says, Hey, if somebody goes to a URL like this   automatically takes them to the detail view. And  if somebody goes to a URL that ends in a results,   like this, then, which is essentially what you're  saying here, hey, any number, followed by results.   Take them to the results, one, and any number  followed by the word vote, take them to the vote,   view. Cool. And let's see what happened. So I'm  going to run I'm going to do Python, manage that   py run server. Cool. And I will open up my Chrome.  And we will go to this guy over here. Okay, so now   we're getting an error is because we actually have  to go to that particular URL. So in this case,   let's go to slash polls, and it should run our  index function. So I'm going to do slash polls,   boom, it ran our index function. What  does our index function say? Let's go   to our views. And that's what it says, Hello,  world, you're at the polls index. Perfect. Well,   what if somebody goes to polls slash five or polls  slash 193? What happens then? It'll take us to the   detail function, and what does the detail function  say? It says, you're looking at question number.   What the question ID cool. So let's try and  let's see what happens. I'm gonna do 193. Okay,   so the cool thing here that's happening is that  you're able to take what's in the URL and you're   able to pass it down to your HTML. So right here  that 193 right. If I make it like some other crazy   number pass that down here, right? So now we're  able to actually take in arguments from our URL   and use them in our code. What if I said something  like this, it'll say, hey, that pattern actually   is not matched. So that's exactly what we want  it. If you don't put in a number here, it should   automatically detect it. Now, if you want to go  to something like slash poll slash number slash   results, what do you do? Okay, so let's say I have  this number, and I go to results, just like that.   And now, it should say something like, you're  looking at the results of question, followed   by whatever it is. Okay? So you're looking at the  results of question, right? Or question two. And   then if you go and try to do this thing with vote,  you're gonna get the same thing. So if I go to my   URLs, it says, hey, go to slash polls slash number  slash vote. So we're going to do slash polls slash   numbers slash votes. And I hit Enter, and it  says, you're voting on question two, perfect.   That's exactly what we should be getting here.  And it's looking great. All right. So it's saying,   hey, like, take a look at this in your browser,  and it will display the placeholders? And that's   exactly what it did. And how does it work? Well,  detail our function that we have, will take in   a request object followed by the question ID. So  when we pass in the question ID to be 193. Right,   this part became 193. And this part is just that  request object. So what they have here? Again,   if you're confused about objects, and what the  hell is going on, it's not completely necessary,   but you should look at some object oriented  programming stuff. Okay. And I do have a course   on object oriented programming, then you could  comment on it if you're interested. Alright,   so the question ID is equal 34 comes from this  thing, and I've explained that to you already,   when you put that in the URL, this dynamically  actually pulls it out. And once it dynamically   pulls that out, because you see it says,  here, it says, question ID question ID,   that's where it's actually pulling it from. Okay.  And that's essentially it. And then it says, Hey,   you don't need to do ugly things like latest  dot html, because it's not necessary. And it's   apparently silly. Okay, so don't do it. And you  should write views that actually do something.   And here, they're saying, hey, look, each view  is responsible for doing one of two things,   either as your return what it's supposed to return  or give you like a 404. And then the rest is up   to you. So, you know, basically, you can have a  view, or it can read records from a database. So   meaning reading records, reading posts, from  a database, Instagram posts, Facebook posts,   or it can generate PDF files, or output XML or  create a zip file on the fly, anything you want.   And pretty much using whatever Python libraries  you want, because Django is 100% Python, so you   have full Python power. And then all Django wants  is that HTTP response, okay. So you can return it   as a string, you can return it, you have to return  it as some kind of an HTTP response. or throw an   exception. Okay, so now, here's what they're  doing. They're like, Alright, we're going to do   something cool. Well, we're gonna do is we're  gonna take like, all of the questions you have,   we're going to order it by the publication date,  and then show the top five most recent ones. Okay,   how are they doing that? Well, I'm going to copy  this, and then we're going to play around with   it. Okay. So we're going to go back to our thing,  and what do they have here from dot models, import   questions, and they're in our poll slash views.  Okay, so this is one thing that we need to do   from dot models, import question, because we don't  have that. So we're going to paste it in here. And   then they want us to redefine our index. Okay. So  we're going to do just that I'm going to change   my definition of what my index function is.  Alright. So how is this working? Well, question   dot question that objects are ordered by. And what  this thing does, is it'll take all your questions   and order it by something. So in our model, if  you look, we have this thing, publication date,   so pub underscore date. So we're going to order  it by publication date. Now what we're doing with   this minus sign is we're saying in the reverse  order, okay. So instead of the oldest publication   dates and showing us the oldest, we wanted to show  it in a descending order. So we wanted to show us   the recent ones first, and then what we're doing  is that we're just and So this will return to us   a list, okay? And then you can index a list in  Python by doing this. And we're just saying,   Give us the first five. So from zero, up to,  but not including five. So 01234, that's five,   okay. And then as output, we're saying, hey, join  all of them all of the questions by a comma. Okay?   So if you want to know a little bit more about,  like how the Python is working in there. So here,   we're doing a list comprehension. And you can  read more about list comprehensions. If you don't   know what that is, it's not too important.  And it's just a cool way of writing this,   you know, instead of multiple lines is writing one  line. And we're just saying, for each question,   give us its text. That's all we're saying.  And then we're saying join it all by commas.   So that's how it's going to output it. So it's  going to return to us pretty much a string, okay?   And then we want to return that. Okay, as our  outputs originally HTTP response output. That's   it. So now, let's take a look at it. So I'm going  to save it and we're going to go to our thing,   and we'll try to go to our index, and where's  our index? It's just that slash polls. Okay,   that should trigger our index. And let's see  what happens. So I hit Enter. And it shows me   all my questions. If you remember, I created three  questions, what's cracking, what's new, what's up,   and it's showing us with separated by a comma, I  could do show it to us separated by three stars,   if I refresh, it separates it by three stars, you  could separate it by an image, whatever you want,   you know, this is just pure Python. Okay, so  that's essentially it. But there's something   wrong here. And the thing that's actually wrong  here is like, Look, you're not gonna have your   toilet and your refrigerator in the same room,  right, you're muddying the water, just like that.   You don't want to have your HTML code and your  Python in the same place, we want to kind of   separate it out. So right now, the design of our  page is in the same place that handles our logic,   okay, so what we want to do is handle our logic  by pure Python in one place, and all our HTML.   And the design of the page should be outside of  this logic, okay. So we want to create something   for that. So what we're going to do, and what  this tutorial tells us to do, is inside polls,   you want to create a new folder, and you want to  call this folder templates. This is important the   case sensitivity of this is important as well as  the name. So if you mess up the name, or you put a   typo, you're going to kind of get messed up here.  also pay attention to the order of all this, okay?   It's under my site. So under polls, you're going  to have templates. And then inside of templates,   you want to create a new folder, and you want  to call it polls. All right. And inside of this   is where you're gonna throw all your HTML file.  So we're gonna create, we're gonna create a new   file in here, and we're gonna call it index dot  HTML. Okay, so just in slow motion for you, polls,   templates, polls, index. Okay. So essentially,  it's like polls, templates, polls, index like   that. Alright, let's go back to our tutorial.  And that's what it's saying. It's saying that,   hey, Django will automatically look for it  and find these templates. And essentially,   to Django, the path will look like polls  slash index HTML, because of how Django   works and looks for these. And you can override  it and do all kinds of advanced stuff, you know,   if you want to read more into that, we're  gonna just kind of keep it a little bit basic,   so everybody can follow. Alright, and now we're  going to put the following code into into that   template. So it's telling us which file to  put that code. And so I'm just going to hit   this button, copy this code. And we're going  to go into our index HTML, and I will paste it   right over here. Okay, what is this code saying?  It's saying, hey, if there are any questions,   then I want you to create an unordered list. Okay,  that's what a ul tag is in HTML. And then what I   want you to say is for a question and so for any  questions, I want you to put it as like a bullet   point and show that question, okay. And link to  that particular question. Otherwise, say that   there are no polls available. So if we didn't have  any questions at all, Elsa, no polls available,   and then end The if statement. Okay, so we're  starting our for loop here. We're ending it here.   We start our if statement here. And then we have  our l statement here. And we have our end if here.   Alright, so that's cool. Now we want to make sure  that we actually link to this index dot HTML file.   How are we going to do that? Here's how. Now let's  update our index view in polls slash views that   py to use the template. Okay, so we're going to  do just that. And also, let's update our index   function just a little bit. So here's a few lines  that we're adding. Let's go back to our views. And   we will see the latest question. We'll keep that  and we'll just paste this in here. All right,   save. So what's going on? We're still getting  those remotes recent five questions. But that's   what latest question list is going to become. And  if you don't have five questions, they'll pick   the top three or top or the recent most for, okay,  something like that. And then what we're doing is   we're loading that template poll slash index HTML.  Okay, so we're using loader, arm. And then there's   something called context dictionary in Django. And  what you can do is you can pass from the backend   server side, pass this to your front ends, your  HTML code, it'll know about it. Okay. So if I go   back to our templates, my index dot HTML, how  is it getting access to this variable, latest   question list? Well, we're actually passing it  in our context. All right, that's, that's what's   going on. And then we're saying, as HTTP response  template dot render, we're saying, hey, send that   context with that request and send it over to  the HTML file. So it sends all that over to the   HTML file, and then our HTML file has access  to that latest question, okay. And this weird   stuff you're seeing here with this with a percent  sign, squiggly bracket, that's Django templating.   Engine. Okay. So it's basically HTML with a little  Django pizzazz. Cool. And so now they're like,   Hey, this is such a common step to load a  template, and then to do template dot render, that   there, they made a shortcut for it, which is just  render. So how can you use that? Like this? Okay,   so basically, you can remove this line, you don't  need this line anymore. And thanks to this line at   the top from Django, shortcuts, import render,  which you should have, we're going to use this   render, and how are we going to do it, we can just  replace all of this. And we can say render. The   first argument is request, okay. And then after  that, the path to that index file, so polls slash   index dot HTML, just like that, followed by the  context dictionary. So in this case, we're just   calling it context. Okay. Sometimes what I like  to call this is stuff for front end, alright,   just to keep it consistent. And just so you  know, the thing that you're accessing on the back   end is not this guy. It's a dictionary context,  dictionary key. So it's actually this string. All   right. And that will give you back this guy. Okay,  so know that once you've done all this in views,   we no longer need to import loader, blah, blah,  blah. Exactly. That's what we did. And now they're   going to show us how to raise a 404 error. All  right, so what happens if it doesn't exist? So   let's tackle the question detail view. The page  that displays the question tax for a given poll,   here's the view. So in polls slash views that  py we're gonna do is we're gonna from Django   HTTP import http 404. So since we're already  using Django dot HTTP to import HTTP response,   we're also going to say http 404. Okay, just  like that, we're going to save it. And then we're   going to come back. And now it wants us to make  changes to our detail view. And it's saying, hey,   turn it into this. So let's turn it into that. And  I'm going to save it. So try accept blocks, all it   does is if there's an error, try except blocks  will catch it. Okay. Try accept block, it is   pretty much the same thing as if then condition,  except that if you're running into some kind of   crazy error tracks, that blocks will catch it and  still run. For example, if you divided a number by   zero in Python, your code will just freaking  crash, right? It'll give you this red blob,   your Apple crash, whatever. But if you run a try  accept block that says, if you get a zero division   error, then Just pass, you'll not get that error.  I'll just pass it. Okay. So what we're saying is   we're saying try to get that particular that one  specific question. Okay. So we're saying, we're   getting that question ID and we're saying get that  object that has that primary care that question   ID, or right, that primary key is equal to the  question ID. So if I pass in a URL like m AP comm   slash polls slash six, right, what is it going to  do? Or let's say slash two, what it'll do is pass   this two in two here, that this will become two.  And the question will get the question object that   has an ID of two in this case, it might be one of  my question that I think is what's new, right now?   What's new question? So then this question will  become the What's New question object? And then   what we do is that we just return that, okay. And  we pass it in our context dictionary, and we pass   that question in here. Except if the question does  not exist, then we raise HTTP four. And we said   question does not exist. Okay. Cool. Let me make  sure to delete that. That's not supposed to be   there. I just added that to show you guys what's  up. Okay. The new concept here, the view raises.   Yep. We'll discuss what you could put in that poll  slash detail that HTML template a bit later, but   if you'd like to quickly get the above example,  working a file containing just this. Okay, so   we're going to get that thing working. Okay, it's  right in here. We're going to create a new file,   and we're going to call it detail dot html. And  in detail, we're just gonna put question just like   that. Okay. So now we got to make it work. And  we're going to go and get our question too. Okay.   So because that specific question exists, look,  it says, What's new? Now, if I change this ID to   one is going to get the question that was what's  up. If I change it to three, it's going to be the   what's cracking. But what happens if I change it  to four? Remember, I only created three questions.   If I change it to four, it says page not found.  And look, the error throws up his question does   not exist. Now, if we didn't have that, right, if  we actually don't have that, so let's go back to   our views. And I'll just remove this. And I'll  just say, instead of rays, I'll just say, pass,   okay, passes the equivalent of saying ignore  to Python. Let's go back and let's refresh.   We're going to get this ugly error, which we  don't actually know what to do with or what   it means. And it is very confusing. But when we  have this when we raise this thing, and I refresh,   you see it says question does not exist. So it's  a lot easier for us to see what the problem is,   is because we know it's coming from here, then  we can like start debugging and know what's going   on. Okay. So that's why that particular thing is  important. Alright, let's move on along. Alright,   so a shortcut. So instead of having this try  accepting or raise, we can actually do a cute   shortcut that says get object or 404. And that's a  method that's in Python. In Django, it comes with   it. So we'll throw that and it's in our shortcuts.  So from Django, shortcuts, import, render, and   actually import get object or 404. Okay, and just  to stay consistent with them, we'll do it in this   because starts with the G and starts with R. So  alphabetical orders and pep eight. Okay. Alright,   so we're gonna go here, we will go to where it  says question in detail. And we're going to remove   this whole thing, okay, make our life easier. And  all we're gonna do is we're gonna say, bam, right?   We're gonna say, Hey, get object or 404. So that  particular question with the primary key of this,   if it doesn't exist, then it'll automatically  say it doesn't exist. And then pretty much the   last line, we'll keep it what it was. We'll save  this. And basically as our context dictionary,   we're saying pass a question as a question. Okay.  So there are three arguments in here, request,   the HTML, passive HTML file as a string, and then  a dictionary. So then we can use it on our back   end. Again, in our detail, HTML, we can actually  use we can see that question. Save. And now let's   try to go to it again. So I'll say four. And now  look, it says no question. No question matches   the given query question, as Unlike no question  object, okay, but if I do three, it finds us and   takes us to it. So this is what we mean, this  is what I mean, when I say Python is really,   Django is really awesome and comes with a lot of  intelligent defaults. Whereas you don't have to   write a lot of a lot of this code, right? It works  on that DRI principle, do not repeat yourself. And   a lot of these things just come built in out of  the box, and it it speeds up your development   time, saves you a lot of those new code lines,  because every new code line that you write,   there's an additional chance for an error. So the  amount of code lines that you can reduce, the less   errors you will make. Plus your code just  looks beautiful and so much more readable,   right get object or 404. Instead of try that  at all. Except object dot does not exist,   right? So it's confusing. Okay, let's go on.  Get object or 404. This is some advanced stuff,   we're gonna skip that for now. Now it says use  the template system. So in our detail dot html,   we're gonna go and I'm going to paste that there,  save it. And let's see what it's saying. Back to   the detail view for our poll application. Here's  what it should look like. Okay, so now let's go   to the detail. And let's see, first, let's just  see what the result is right? And then we'll talk   about it, I'll hit enter. What's cracking is  showing it to me in a nicer way. Let's do two,   it's showing it to me in a nicer way.  What happens if I do four? Same thing,   no question matches the given query. Okay,  so what are they doing here? They take your   particular question and they wrap it up in  a h1 tag in HTML, anything that's an h1 tag,   will make it's called the heading one. And you can  go all the way down to heading six, heading six   being the smallest heading one being the biggest  boulders. So we have an in a heading one. And   then right underneath it, we say for choice in  question, dot choice underscore set dot all. So   for all of the choices, as like at choices as in  particular answers, you can have to each question,   right, though, those answers are the ones that  actually get an upvote. Or there's no downvote,   sign up vote, show me all of those answers,  except in this case, we don't have any answers   or any choices. So that's why it's not showing  those. How is it working? The template system   uses dot look up syntax. So you'll do question  question tax. So we'll go into the question,   and then it'll access a question or score text.  Another thing to notice if you're more advanced,   if the question underscore text attribute did not  exist, it would go and try to access it as a list   index. Okay, so imagine if it was like if you  did question dot zero or something like that.   So you're still using dot notation. So that's  something that could trip you up later. Okay. It   would have tried a list index lookup, okay. And  then method calling happens in the for loop. So   this for loop method calling is happening there?  Because you know, you're doing question that   choice underscore set dot all, okay. And then  it's interpret as Python code, which is cool,   like right here. And it returns an iterable of  choice objects. And then we iterate over it,   right. So that's why we use a for loop, and then  we iterate over it. Now. Remember, when we wrote   the link to a question the poll slash index HTML,  so let's go to our polls slash index dot HTML,   you can see what we did here. Right? So we said,  slash so for the links. We said slash polls slash   this. Right. So let's go take a look at this page.  One more time, we're going to go right here. And   I'm just going to hit pause and hit enter. So  you can see how it's showing me what's cracking,   what's new, what's up to each of this. And when  you click into it, you go into the detail view,   right? Kind of like when you click into a blog  post. And also under What's up, you can actually   see the choices. So that's just a recent thing  we just added. Right? So how is that working?   How are we linking it and how we're linking and  we're saying slash polls, slash that question ID,   which matches, one of the paths in our URLs are  p y. So if I take you to my URLs, it'll match   the path of this guy. And that takes you to the  detail view. And that's how we can see the detail   view. So let's go back, but we're hard wiring the  URL paths this way if we have a lot of URL pads,   or logic and get messed up or if we change if  we go in our URLs that py and I, I don't know,   change this path to be something else, right? It  has like, it says polls here, again, followed by   something else, it could like mess us up. So what  we want to do is we want to use it in a dynamic   way. So that's what they're showing us here. So  they're saying, hey, replace this guy with this   guy. So we're gonna do just that. Okay, so we're  gonna go back to our index HTML, and we will just   do this. Okay. So now what this is saying is,  for the URL, use detail, detail as in this,   that's where we're getting the name from. And  then as the argument passed in the question.id,   so this question, since we're looping over it, if  you do question dot use a dot notation, it'll get   you that particular questions ID. So question  ID, that's what you pass in as argument. And so   then when you go to your URLs, to this question,  ID, that's what it's going to pass. Okay, that's   essentially it. And I believe you should also be  able to do question underscore, ID equals that,   but in this case, we're just going to keep it  like this. Okay. So no need for keyword arguments.   Okay. And then in in between here. So that's what  it's going to link to, it's going to link to the   detail view of that particular question. And the  text that we're generating is just from right   here. So that's question dot question underscore  text. If you are confused by this, look up stuff   on HTML, okay, and look up how links work in HTML.  Again, I'm not going to go into too much HTML,   because that's outside the scope of this tutorial.  Okay, and that's how it's essentially working now.   namespacing url names. It's basically just telling  us like, Hey, look. So let's go down over here.   Let's just make sure we're not missing anything.  Okay, from the top. Okay, they're saying,   if you want to change the URL to something else,  perhaps it's something like polls slash specific   slash 12. So this is something that I've already  said, but but they're just reiterating here. And   they're saying it like, if you change the URL,  it's still going to work now that we change it to   be the dynamic way. Okay, so now we can change our  URL pattern to whatever. And it's not hardwired   anymore. And now they're talking about namespacing  URL names. Okay. So this way, you want to make   sure that all of your apps actually have, there's  no way for like, right now we only have the poles   app, right. But what if we wanted to have more  apps inside of this, then what can happen is   that if any of our HTML files name matched, so  let's say you have a polls app, and it has an   index dot HTML file, right? What if you had a blog  app, and that also had an index dot HTML file,   now you're gonna have a collision. So what we do  for that, that's, that's the reason why we create   under templates, another folder called polls. And  if we wanted to add templates for our blogging   app, that's why we would have an app called blog.  And then under that, we'd have templates and then   under that, we'd have blog, and then under that  would put our HTML stuff, okay, that's the reason   why we do it like that. And this way, there's  going to be no collisions. Okay. Now change   your poll slash index dot HTML. So let's see what  it's saying here. So we can have our app name, app   underscore named avatar name is equal to poll. So  this is in our URLs. py. So let's go right there.   urls.py. And they're saying, hey, add that guy  right over here, okay. And pretty much everything   else we want to just leave as is. Now change your  poll slash index dot HTML template from this to   this. So in our index HTML, we're gonna go right  here, and we're gonna paste that guy. So notice   the difference. All we did is we do polls equals  d polls colon detail, okay? That's really the   only difference. There's no other difference. I'm  gonna save that. And this way, our URLs will never   collide. And everything has a proper name spacing,  right, because right now we created a detail for   our problem. What if you want to create in what  if you had an add a new app called blog, and then   create details in there. You don't want it to just  be called detail because it's going to collide   with the polls detail. But now because it's  polls colon detailed, then later, you could do   blog colon detail, or Instagram, post colon detail  or Facebook status, colon detail. And this way,   you can differentiate all of those different apps  you have within one of your Django projects. Okay.   writing your first Django app, Part Four. Alright,  so we're continuing a web poll application. And   we'll focus on simple processing, simple form  processing and cutting down our code. So the big   things we're going to be doing is how do you add  a form, that where you can submit information to,   so basically, it's going to be a form is gonna  have radio buttons, you're gonna pick your choice,   you're going to click on it, and then you're gonna  be able to send that data over, that's number one   big thing we're going to be doing. The second big  thing we're going to be doing is cutting down our   code using something called Django is a generic  views that are super, super powerful. And it makes   your code a lot more readable, and it stops you  from doing the same thing over and over again.   Okay, so it makes things a lot simpler for you. It  does have a little bit of magic involved. But hey,   that's what I'm here for. And I'm gonna break  it down. So let's jump right into it. Alright,   so writing a simple form, I'm going to copy this  guy, and then I'm going to break it down to you,   you my friend should not be copying, you're  learning this stuff. You should be writing this   down line by line and going, huh? How does this  work? Ah, that's how it works. Oh, hmm. And then   you should be googling it and looking it up. Okay.  For me, I know how this works. I don't want to   waste my time a copy, paste it and then break it  down for you. capiche. Let's get going. Alright,   so let's pop open our atom. And we will go into  our detail dot html. And we're going to put this   over that. Okay. So what is going on at a higher  level? We have a for our heading one. So this   is where, what the specific question is, okay, so  what's up? What's crackhead what's pop and things   like that? All right. Here, this line is saying,  Hey, man, look, if there are any error messages,   I just want you to freaking show them. That's all.  And this guy over here is just a form where you   actually submit and vote, okay, at a high level,  that's all that's happening. Okay, now getting   down more into the code level. This is pretty self  explanatory is just h1 tags is just HTML, here is   a little bit of Django going on. So here we're  saying, if there are there is an error message,   then show it, okay, and show it covered in strong  tags, that looks nice. And then here's where we're   creating a form. So we started the form tag here  and the form tag here. The action is to go to this   specific URL, so trigger this URL. So basically,  action means what the heck happens when you submit   a form? Right? what's an example of a form?  You? Every almost every website has it? Okay,   so you going on Instagram and logging in, you  are submitting a form you logging in on YouTube,   you logging in on Facebook, you are submitting  a form, you posting a status hitting post,   you are submitting a form, okay. So  that's essentially what's going on.   So what we can say here for action, once  you submit a form, what should happen,   okay? One thing you could do here is just type  in facebook.com. So once you submit this form,   it just takes you to facebook.com. Okay, you can  certainly do that. Except in our application, what   you want to do is, once somebody submits a form,  you want to send them over to some other part of   your app with that information with that data. For  example, if somebody adds shoes to their cart, it   then takes them to the new page with information  where they previously added shoes to their cart,   and then shows the shoes and the shirt and the  tie on. proceed to checkout page. Okay, that's   essentially how you use forms in real life. Okay,  so here we have it to Hey, take me to the vote.   View, okay, or the vote function in our views  file. Cool. CSRF token so there's something called   cross side. I forget what it fully stands for.  Let's take a look at it. They mentioned it cross   site request forgery is okay. So it's a security  mechanism and All you have to do is really not   to worry about it too much. All you have to do is  just add that token. Okay, so actually, that's it,   that token doesn't even need an end. That's it.  This is just a line that you add, usually when   you're adding Django forms unless you're using  something like crispy forms, which is, again,   outside the scope of this tutorial. So that's what  this line is here. We're doing a simple for loop.   Okay, the for loop goes through all the question  choices. And what are question choices? Well,   remember each, so you have question, and then  one question can have multiple answers to it.   Those answers are the things that get voted on. So  what we're doing now is listing out all of those   answers or, or those choices. And, and, and I'll  show you right now, how al actually look Okay, so   let's go ahead and check out what this looks like.  So now, we're gonna go over to our app. And let's   click on what's cracking. And you can see it says  what's cracking followed by vote right underneath   that. Okay. Let's go to what's up. What's up has  two choices. Remember, I had not much and the sky?   Those are two possible answers. kind of funny.  I don't know which one I like more. But yeah,   you could you could vote on one. And then you  could certainly hit vote, okay. Yours is not   going to look as big as mine. That's because I  have it zoomed in. So you could see on my 5k,   iMac retina screen, and you can pick whichever  one you want. That's it, and then you hit vote,   boom. Okay, you're voting on question one, it will  redirect you to that. Cool. So that was that the   radio buttons are coming from these lines, okay,  how's this working input type radio, when you do   this, then it creates those radio buttons on the  side, okay. I for ID something you don't have   to worry about too much. But for ID, we're just  using the built in Django templating systems for   loop counter. So we'll give the id 1234. As it's  looping through. And yeah, values, just a choice   that ID and Name, we're just calling a choice.  Name is very important. Once you get this on the   server side, the back end, you could reference  this post data using that particular name, okay,   so you're gonna be able to do something like  request, I post bracket choice. Okay, and then   label for, that's just for labeling purposes.  Again, not incredibly important to what we're   doing. And then we end the loop right over here.  And then right over here, we're saying this form   is basically what we're saying is like, put that  Submit button, and then just call it vote. Okay,   so that's why you see, you know, if I called  it something else and saved it and refresh now   calls it that. So here we're saying call it  vote. And then for type, we're going to say   it's a submit button. So the type which is  going to give us submit, so once you hit it,   it sends that information over to the next page.  Cool, let's go back to our tutorial. Alright,   so that's pretty much what is gonna explain to us,  but let's just see and make sure we're not missing   anything. Right, so the value of each radio button  is associated, is associated question choices ID,   the name of each radio button is choice. Yep.  That means when somebody selects one of the   radio buttons and submit the form, it'll send  a post data choice, where a number is the ID   of the selected choice does the basic component of  HTML forms, okay? We said the forms action to that   particular URL, and we said method is equal to  post. So here's another important thing to note,   this is pretty important. Whenever you're  generally submitting data, or filling out a form   and sending it over, you want to use post request.  Because it's safer, and it's better. You don't   want to be using GET requests when you're sending  data over because it's insecure, and you can get   screwed. Okay, so simply put, as opposed to get  it's very important, because the act of submitting   this form will alter data server side, whenever  you create a form that alters or data service   side, use method post. This tip isn't specific.  Django is just good web development practice. For   loop counter indicates how many times a four tag  has gone through its loops. Okay, I've explained   this already. Since we're creating a post form, we  need to worry about cross site request forgeries   and I've already gone over this as well. Okay.  And that's why we're using CSRF token. All right,   now, let's go Create a Django view that handles  the submitted data and does something with it.   Remember, in tutorial three, we create a URL con  for the that includes this line. So we already   have this line, we don't have to add it. So if  I go to my URLs dot p y, you'll see four votes,   I have this line right over here, and so should  you. Alright, now let's add the knowledge,   we're gonna create a real version for our vote. So  up until now, we had functionality for our vote,   but it was just dummy placeholder didn't really  do anything. Okay, so now we're gonna actually   add real functionality, what are the few things  we need that we don't have? Let's see, we'll need   HTTP response redirect, because we don't have  that. So we're gonna put that in. All right,   we're gonna save. What else do we need? We need  from Django dot URLs, import reverse. So we're   going to add that in and hit save. And then that's  essentially, essentially and then it except we're   gonna have choice right here, save cool. Okay, now  we're gonna go in our vote, and we need to add all   of this code. Okay, and I'll break it down for you  right about now. Okay, so what's going on here?   Question? We get that particular question, or we  throw 404 error, we then get the answers for that   particular question. Okay, or selected choice.  one specific choice, that's what we get. Okay? So   for example, whether the choice is going to be the  sky or whether the choice is going to be something   else, right? It's not going to show it to me right  now. Cuz the app is offline right now the server's   close. But since we had two choices, and you  couldn't vote for this choice, or this choice, how   are you going to know which one is sent? Right? So  that's what we're trying to pick here. Whichever   choice you select the radio button next to that's  whose primary key we're going to be passing in.   And how we get that as request our post choice  request, our post is just a dictionary, and you   could index you could get pull out the key choice  from that. Okay. Just to have it make sense. Let's   see, let's run this code. So what is it saying?  The problem is right here. Alright, we're gonna   run this code. Cannot import name reverse http  404. Let's see where that error is coming from.   Hmm. Right there, reverse, okay. And you could  still have http 404. Not a problem. All right.   So let's go back to our app. Let's go to what's  up. And also, let's go back to this, save it,   come back, let's refresh. This should save votes  here. Now, when I hit the sky, we're gonna see   what happens. So I'm going to hit inspect here.  And our console pops up, right? We're going to go   to sources. console is looking pretty insane  right now, but that's fine. I'm going to click on   network. And we're gonna click vote. So we're just  voted for the sky. Okay, now in our network. Let's   see if we can zoom out a little bit because it's  a little too crazy. Alright, so in our network,   we can see that the request method is post, right.  And we can actually check out the response. And in   this case, it says the response failed. Let's  click here, right now, when I click results,   because it was sent to results, it says you're  looking at the results of question one, right?   So there is a response. And now if I look in the  headers, it tells me the request method right now   is get, and it tells me kind of all the things  that go along with it. Right. So let's try it   out again. Let's pick another question. Not much.  And vote. Let's see what happens. So 302 found,   right. Okay, so let's go here, preview response,  failed to load response data. If I go and results,   it's showing me are looking at the results of  question number one, okay, so pretty much it says   the same thing and it's giving my statuses What  do these mean? We're gonna break it down a little   bit later. Okay. So let's go back to our tutorial  and go down. index HTML. Okay, so this is looking   good, our views. It's looking fine. Cool. Now So  yeah, so basically we're selecting the specific   choice from here, whatever we get, we send over  in our request. And then we throw an accept choice   that we throw an exception here, okay? And we  also check for if like the choice does not exist,   or if there's an here. And in the case that the  choice does not exist, we return polls slash   detail dot html, we render that and we return  that question object. And for error message,   we say that you didn't select a choice, okay? So  if you somehow selected, you know, nothing. And   otherwise, if we have selected it, and we haven't  ran into this issue, we want to say is for that   particular choice, we want to upload it by one.  So we're in incrementing, the vote count by one,   we want to save it. And then we redirect. Okay.  So we're going to go into more depth of that.   But let's just check this part out one more time.  Refresh. Let's hit inspect. Let's go to network.   Let's select this guy, let's click vote. So you  can see, okay, so that's that's exactly what I   needed here. So a little hard to see though.  So you can see when I scroll all the way down,   that it actually pulls out the form data. And  it's telling me that the choice I selected was   the second choice, right? That's an important  part. And it's also has a CSRF middleware token,   which, remember we did CSRF underscore token,  that's where it's generating now from, but the   choice is the most important one. So whether it  was choice one or choice two, and we're picking   this based on the choice ID, okay. So that's  essentially what's happening. Now, if I go back,   and I pick Not much, and I vote, and when I  go back up to vote, and I go all the way down,   you'll see that it's showing me choice one, right.  So that's the thing that we're actually pulling   out. So this will essentially turn to a one or a  two. That's what I was trying to get at earlier,   but it was just my screws too big. So it was hard  for me to show it. But that's what gets selected   here. And once this evaluates to something like  a one or something like a two, this whole thing   evaluates to that specific question object.  And then we up voted, and then we save it,   and then we redirect. Okay? The reason why you  so when you're done with all of this, you don't   want to say, hey, go back to the home page, or  you don't want to just say like render the home   page. Because if the user refreshes, it will keep  submitting that data over and over again. So like,   imagine, right, if you were about to pay for  your credit card, and you buy like, whatever,   right? You buy shoes, or you buy grocery. If you  refresh, like something happens during half of it,   then it gets submitted. But then you go back  and you refresh, or you resubmit. It shouldn't   let you resubmit and pay again, right? Every  time you refresh, and then all of a sudden,   you're charged like $300? Or what if you were on  an online trading app, and you just put down like   $3,000 for Bitcoin. And then you refresh, or you  go back and forward a page and it reads a mess.   3000 $3,000. Again, you're going to run out of  money pretty fast, right? $9,000 like that. So   it's a pretty serious issue. So what you want to  do instead is redirect This prevents data from   being posted twice if a user hits the Back button,  okay. There's a better way to do redirect, which I   think they'll show us later. But it's essentially  I think, from shortcuts, you can pull out redirect   and just call redirect, and it's much simpler.  But they do it this way. Should you be response,   redirect, reverse and then take me to the results  view, right. So it takes you back to this results   view. And for argument it just passes in the  question ID cool. So that's looking good. Now   let's play around with it and let's just check out  what happened so I've already voted for like one   or two questions multiple times. Let's see what's  going on on our database. I'm going to go in   Python manage that py shell so we're gonna do is  from polls dot models. I'm an import choice. And   I'm also going to do from polls dot models, import  question. Question dot objects, dot get Let's say   we want to get our first question or what's up  question. And we're going to save this question   as like q or something. And now what I'll do is  I'll do Q, that choice underscore set that all.   Now show me all the choices or answers for it.  And then I'll pull out the, the sky one. And then   for the sky one, we can see it's vote count. In  models, I forget what is voters votes. So you can   see that it has two votes. And then the other 1/3  one, it also has two votes. So it's a tie. Okay,   so both have two votes. So you see that what  we're doing on our front end, and we're voting,   it's actually being counted here, okay. Usually  where it says choice underscore set, that's kind   of weird. So how you want to say it is like cute  choices. And, again, like I've mentioned in our   for, at the end of our first video, like if you  want to change that, I'm not going to change it   now just to stay consistent with Django, official  docs. But essentially, like right in here, right,   right in the top, we can actually write something  called related underscore name, and then fix this   issue, like right there. call it something like  related underscore name, and give it choice says,   okay, something like that. But we're not going  to do it right. Now, we're going to stick to   a Django because otherwise, I'll have to make  migrations and things like that. Everything is   fine. For now. I'm going to exit out of this. And  I will just do Python, manage that py run server,   and just go back to using our regular app. Cool.  All right. So now let's see what they want us to   do. So that's all good. That's working. Alright,  let's see what they're saying here. requests are   post is a dictionary like object lets you access  submitted data by key name. Yep. So that's how we,   we use the choice key name. requests that post  values are always strings. Cool. Note that Django   also provides request I get that's by default,  that's there. But we're explicitly using requests   our posts and our code to ensure the data is  only altered via post call. It will raise a   cure if choice wasn't provided in post data, the  above code checks for key error right over here.   And redisplay is the question form with an error  message if choice isn't given. After incrementing,   the choice count the code returns an HTTP  response redirect rather than a normal redirect.   This redirect takes a single argument the URL to  which the user will be redirected to the following   point for how we construct the URL in this case.  And you should always return an HTTP response   redirect after successfully dealing with post  Okay, we're using reverse function constructor,   this function helps avoid having to hard code a  URL in the view function. It is given the name of   the view that we want to pass control to and the  variable portion of the URL pattern that points to   that view. Cool. So right here. Now after somebody  votes in a question, the vote view redirects to   the results page for the question. Let's write  that view. So now, it should point us back to the   results, and we're going to write it okay. So here  is what it should be looking like, let's check our   results. Pop that bad boy, whoops, pop that boy  right in here. And we just say get that particular   question. or otherwise, throw four or four. And  once you get it, take me to. And once you get that   question, take me to results dot html. So you can  already see there's some similarities, right? Like   here, there's a similarity and here's there's a  similarity. Both of these have to do with getting   that one particular question. So think of it like  you're getting the result detail view for both of   them. But in one, you're sending me to detail that  HTML and the other one you're selling, sending me   two results, that HTML, okay. And we're gonna kind  of address this issue of like our code being a   little bit repeated. This is almost exactly the  same as a detail View from tutorial three. The   only difference is the template name. We'll fix  this redundancy later. So they mentioned that. Now   let's create a poll slash read zoals dot html.  So we're going to go in and create a new file,   I'm going to call it results dot html just like  that. I'll paste it here. And we'll go to our app.   And we'll vote for the sky. And then it'll take  us to the results of what's up and look at that   now much says two votes and the sky. three votes,  vote again. And then it takes me back to the vote.   And I'll vote for not much. All right, so it's  coming out pretty cool. So far. All right, is this   is exciting, guys. This is exciting. So now, what  is this code saying, Let's read our code who just   added header unordered list unordered list, the  loop is saying go through all of the choices, or   all of the answers. I don't know why they call it  choice, I just think is a bad name. And get that   choices choice text, put two dashes in between it.  So for example, this would turn this whole thing   would turn into like the sky or not much, followed  by the number of votes, followed by it saying   vote, choice out votes, pluralized. Right. So what  this is doing is it's either gonna put an S here   or not. So for example, let's go here. So if you  only had one vote, it wouldn't this would turn   into nothing. And if you had multiple votes, it  would turn into it would put an S here. Okay, so   it's a pretty cool way of pluralizing something.  But you're doing choice dot votes. So this will   evaluate to like, let's say three, and then you're  piping it over to pluraleyes. And then pluraleyes,   will be like, hey, yes, you should pluraleyes and  put an S here. And then I'll put like an S like   that. Okay. Cool. With that said, That ends a for  loop. So you're doing not too much here. And then   what you say is like, Hey, you want to vote again?  And how you how you're doing that is you're just   providing a link to the tax vote again. And it'll  essentially take you to the detail view of that   particular question. Okay. So if I hit vote again,  it takes me to the detail view of that question,   what's up, not much vote, it takes me to the  results view. If I hit vote again, it takes   me to detail view, click here takes me to the  results view. So this app is starting to have some   functionality again. So again, that's pretty cool.  Let's go here. Let's check out now go to polls   slash one in your browser and vote in the question  we did. It gets updated each time you vote if you   submit the form without having chosen a choice,  you should see the error message. Okay, so let's   see if we can try to do that. Let's hit vote.  And it says you didn't select a choice. Perfect.   That's exactly what we want it. Note, the code for  our vote view does have a small problem, it first   gets the selected choice object from the database,  then computes the new value of votes, and then   it saves it back to the database. If two users of  your website try to vote at exactly the same time,   this might go wrong, the same value, let's say 42,  will be retrieved for votes. Then for both users,   the new value of 43 is computed and saved. But  44 would be the next expected value. This is   called a race condition. If you're interested,  you can read avoiding race conditions using F to   learn how you can solve this issue. Okay, that's a  little bit advanced, it would have to be literally   at the same like fraction of a second. could it  happen? Yes. If you're trying to scale your app   to a lot of users? Yes. Should you worry about it  right now? Hell no. So let's continue. Alright,   so remember what I mentioned in our views,  some of the code is looking similar like here,   these are detailed views, right? They're showing  the specific question. And they need one specific   question. Looks a little redundant, right? And  then we're using also specific question like   allowing us to vote here, but these, there's a  little bit of redundancy going on. So how can we   address this? How can we manage this in a better  way? Well, luckily for you, Django has something   called generic views. These are class based views  that essentially have you once you use them. You   don't even have to write down much real code. It  just does a lot of the things automatically in   Pretty intelligent way. So I like this and check  it out. Alright, the detail and results views   are very simple as mentioned above, but they're  redundant, okay? The index view, which displays a   list of poles is similar. These views represent a  common case of basic web development, getting data   from the database according to a parameter passed  in the URL, loading a template and returning the   rendered template. So we pass stuff, and we get  it from the URL, and then we load up a template   and we return the render template. That's  essentially what we have been doing. And when   I say return the render template, another way to  say it is returning that HTML file you're looking   for right or that page on the front end that you  see. Because this is so common, Django provides a   shortcut called generic views system. Generic  views, abstract common patterns to the point   where he doesn't even need to write Python code  to write an app, you could literally be sleeping,   and the app just writes itself. Let's convert our  poll app to use the generic view system. So we can   delete a bunch of our own code, we'll just have to  take a few steps to make the conversion. We will   one, convert the URL cons, delete some of the old  unneeded views and introduce new views based on   generics. Generic Django views. Alright, read on  for details. Okay, so why the code shuffle? What   they're basically saying is, hey, you should know  basic math before you start using a calculator. So   why did we do this up until this point, only to  now refactor our code? Will we have to refactor   our code all the time? No, you will not. Next  time, when you're doing your app, you already   know how the class based views work, you'll start  from more generic class based views. So basically,   what they're saying is like, hey, look, we don't  want to just give you the calculator before you   can do basic two plus two, or in my case, in one  of my videos, I think I had to do 2000 divided   by 10. On a calculator. That was a pretty sad  moment. And that has a lot of upvotes makes me   sad to this day. I wish my editor took it out. Oh,  well, you don't always get what you want in life,   but Django generic views comes pretty close. So  let's keep going. Alright, amend URL con, First,   open the polls slash URLs, r p, why you're  on Khan, then change it like so. So we're   going to go and pull slash urls.pi. And I'm just  going to paste it over this bad boy and explain   what the heck we just changed, right? So besides  the fact that we took out some notes, what else   just changed? So let me let me take this out. So  you can kind of see it side by side and really see   what changed. So if you look at this index thing,  all the change before it was just dot index,   now it's index view.as. View, detail view as view  results. view.as view? And those are the middle   arguments that changed, right? What are the other  arguments that changed? Everything after the name,   all the name, keyword arguments remained the same.  But there was something else that changed. So here   it says question underscore ID everywhere. But in  the new one, it says PK everywhere if you notice,   right, so that's another big change to keep in the  back of your forehead. Alright. That's what they   mentioned over here. Cool. So that's essentially  what we're going to be focusing on here. So here,   we still have question ID, okay. Now, when we're  using these generic views, they take things in as   PK, and they'll explain that later. And now we  need to make changes to our views. We're going   to remove our old index detail and results views  and use Django as generic views instead, to do   so open and change it like so. So we definitely  need this generic thing. So we're gonna do, we're   gonna go to our views. And here we're going to  do from Django dot views import generic. Alright,   so we got that. Other things that we need. Now we  need to make a class here. So I'm gonna completely   remove this guy and add a little class here. How  will this work, it will automatically know which   template to use based on this variable. These  variables are not just random, you can just call   it this, it will not work. These variables have  to have this specific name for them to work. Okay,   this is something important for you to remember.  Django does have a bit of magic but once you   learn how it works, It'll be really, really  helpful. Okay. So template underscore name,   you have to use this variable, we assign it  to the index HTML. For a context object name,   we say latest question list. And for a query  set, we're just returning the last five published   published options. Okay? So this we're saying,  only be referenced if somebody says this. So   when somebody says this, you can get me that,  okay. Let's go in our class detail view. So for   our detail, all we need to write is instead of  doing this get object 404, passing the question,   passing the primary key and all that stuff,  and saying render requests, followed by the   context dictionary and all that. It's pretty  simple. How is it working? Well, it's actually   pretty cool. Um, okay, so let's go back to our  URLs. And since we're passing PK right in here,   it already has it, you don't even have to pass it  as an argument or anything. Which model? Again,   these variable names matter. We're telling it use  the question model, so it's directly communicating   with this model right over here. template name,  we just give it the template name. And that's it.   It knows what to do. Okay. pretty beautiful. Now,  let's do the same thing for results view. So it's   going to change from this obfuscated looking code  to something pretty simple, check it out. Clean,   right? Looks a lot cleaner, no need for request  and question ID no need for a get object or 404.   No need for passing in question or primary  key, no need for saying render request. And   passing in a context dictionary, it just  does it all automatically. And then vote,   we're gonna keep it the same. Okay, we're gonna  hit Save. Now we're using two generic views here   list view and detail view, respectively. Those  two views abstract the concept of display a list   of objects. That's one concept. So list view is  going to do that. And then the other concept is   display a detail page for a particular type of  object? So are you looking at the home page of   Instagram? Or are you clicking into one particular  post, I'm looking at its detail. A generic view   needs to know what model it will be acting upon.  This is providing using the model attribute,   which is this. The detail view generic view  expects a primary key value captured from the   URL to be called pk. That's why here it has to be  called pk. So we have changed question underscore   ID to PK for the generic views, but not for the  non generic view. By default, the detail generic   view uses a template called app name slash model  name underscore detail dot html. In our case,   it would use the template the following template,  right. So if I go in my views, Paul, so app name,   our app name is polls, slash results dot html,  so slash slash the model name dot html, okay. In   our case, we just called it results at HTML. The  template name attribute is used to tell Django to   use a specific template name instead of the auto  generated default template name. We also specify   the template name for the results list view. This  makes sure that the results view in the detail   view have a different appearance when rendered  even though they're both a detail view behind   the scenes. So they're both a generic detail  view. Okay. Similarly, the list view generic   view uses a default template called similar to the  other one, we use template name to tell ListView   to use our existing one. So by using template  name, right over here, we're telling it which   one to use specifically. In previous parts of the  tutorial, the templates have been provided with   a context that contains the question and latest  question list context variables. For detail view,   the question variable is provided automatically.  So the question variable is provided automatically   instead of us even having to pass it in as  a context dictionary because generic views   are smart. Since we're using a Django model,  our models called question Django is able to   determine and improve Britain name for the context  variable. That's why it would pull out question.   This would be the variable name that you can use  automatically on your front end in your templates.   However, for ListView, to automatically generated  context variables, question underscore list. So   if it's a list of things, right, like the list  of choices, or those answers, it would call them   question underscore list. to override this, we  provide the context underscore object underscore   name attribute, so we override it. And we give it  our own name. If we didn't give it our own name,   we'd have to access it using question or score  list. But by giving it our own name, now we can   access it on our template side as latest question  list. Okay, specifying that we want to use latest   question list instead, as an alternative approach,  you could change your templates to match the new   default context variables, but it's a lot easier  to just tell Django to use the variable that you   want, run the server and your new polling app  based on generic views. So let's actually give   it a try. My server is indeed running, I'm  going to refresh, I'll take a vote. And it   voted correctly. I'll vote for the sky. And it  looks like it votes correctly. I will go to the   polls like homepage, just polls. And it shows  me all the detail views for all of them. Right,   what's new? And when I go on, what's up,  not only does it show me the detail view,   but it also shows me the choices that go along  with it. So working fan in a fantastic way.   Right, your first Django app, Part Five? So what  are we doing in this tutorial, we are going to   be doing a lot of automated testing. Okay,  so what the hell is automated testing? Well,   here, let me break it down in a simple, easy to  understand way. For you mere mortals out there.   Let's say you have something like Amazon, right?  Something giant with millions of lines of code?   Are you really going to like every time you add  a new feature, are you going to test all of the   older features to make sure that they're working  correctly? Probably not, it's going to take up   a lot of your time plus, you're going to kill  yourself. So what you're going to do is actually   write these automated tests. So every time you  add a new feature to Amazon, let's say that you   add this new cool feature that recommends new  shoes, you want to make sure that the ability,   when user clicks add to cart, that still  works when a user clicks Checkout, that still   works. So what you would normally do is go and  manually test it except because Amazon is so big,   you're not going to be doing that. So you're  gonna write automated test, I'll test all of   those things every time you add a new feature. So  when you add a new feature, it automatically tests   everything that was before it. That's the point of  testing. Okay, that's kind of the beautiful thing   about it. Okay, so why you need to create tests,  tests will save you time. Yep, they will save   you a lot of time. Because let's say you were to  run into a bug or something unexpected behavior,   you will know exactly why it's happening.  Or you'll catch on to it a lot faster. If   you have code that tests those things. as you go  along. rather than waiting till everything breaks,   the whole world comes falling down. And then  you're like, wait, what went wrong? Yeah, good   luck finding the bug in your millions of lines  of code, right? You want to quality test, each   thing as it comes in. Tests don't just identify  problems, they prevent them. Okay, so this helps   you identify any problematic new bugs that could  be coming in. And not only like, identify them,   but prevent them before it even happens. almost  think of testing kinda like if you just hired   people without interviewing them. I mean, you  would have no, right, you would hire people   like this guy. And you would have people who you  would have no control over, don't know. And like,   let's say something was going wrong in your  company, you're not going to know who to blame,   because you never really tested any person, right.  But if you run through an interview or a test with   them, then oftentimes you don't even have to hire  them. And you can kind of prevent it. Before that   problems spreads. Or if they're awesome, then you  can add them in right to your company. Tests also   make your code more attractive. So basically,  like, your code will look nice if you have tests   otherwise, developers won't take you seriously and  test how teams work together. So if your team is   working, and some complex applications will be  maintained by teams right and test guaranteed   that call leagues don't inadvertently break your  code, and that you don't break theirs without   knowing. So this way, it also helps you when you  get employed and you have a job. You know, a lot   We'll help you identify like where the problem is  coming from and the people who are working with   you on your team, they know exactly what you're  thinking. And won't cause problems in your code   either. So those are the benefits of testing.  Now you have some basic testing strategies,   something called a test driven development,  it's a pretty common thing. It's called TD d,   t, d. d, okay? And basically, it's like testing  as you go, rather than wait till I write my   millions of lines of code and then freaking  test it right? Wait till I have 30 employees,   and then I'll ask them and interview them and find  out like, don't do that test as you go. Okay. Now,   all we're gonna do is we're gonna write our  first test. So, oh, we identify our bug who   look at that. Well, they purposely planted a bug  in our code. And now we're going to use testing   to solve it. Okay, we're gonna go Sherlock Holmes.  Alright, so fortunately, there's a little bug in   the polls application for us to fix right away.  The question was published recently. So you guys   remember that a little method we had was published  recently in our models for question. Well, it had   a little bug. And basically how it works is the  method returns true if the question was published   within the last day, which is correct. So if it  was within the last 24 hours, it shows you true,   but it also shows you true if it was published in  the future. Okay. So it shouldn't say that it's   recent, if it was going to happen in the future,  right? You wouldn't say, Oh, I recently got a car,   if you're going to get a car 20 years from  now, when you finally get a job, right? So   I'm just kidding, you probably already have a job  I don't. Let's continue to check if the bug really   exists using the admin create a question whose  date lies in the future and check the method,   check and check the method using the shell. So  first, we're going to check what's going on using   the shell. Alright, so let's go back to our code.  Alright, so the first thing we're going to do is   run our Python. So we're gonna run that from  we're gonna do Python managed up py shell,   don't just do Python and hit enter, like an idiot  like I kind of did. So once you run the Python   with this particular shell, then what happens  is you can like import your, you know, models   and everything. Okay, so now import date time,  we're going to do from Django dot utils, import   timezone. And then we're going to do from polls  dot models import question on. With that said,   Now we're going to create a question instance with  the publication date, 30 days in the future. Okay,   so how does this work? We're going to create a  variable called a future question. And we're gonna   create it from the question class. And we will  say the pub date is equal to timezone dot now,   so we're saying that it's published right  now. And then, but to that timezone, now,   we're going to add some time to it. Okay, so  we're going to do date, time, dot time, delta,   and we will do days is equal to 30. Just like  that. Okay, and then we're going to hit enter. So   I say i'm saying is like, right now plus 30 days,  which in other words, translates 30 days from now.   Right. So basically, right now, where I am at and  what my current day for me is February 20. Okay.   2018. So it's gonna do February 20 plus 30, days  after February 20. Okay, so no, it's not gonna   be February 15. It's gonna be March something,  right? Cool. Was it published recently? Now we're   going to ask it, and it should say no, it's not  published recently, right? It should return false,   except that it returns true. So there you have it,  we know that something with our code is broken,   right? So since things in the future or not  recent, this is clearly wrong. Now we're   going to create a test to expose the bug. So right  now we expose the bug through the command line,   right? We just use the interactive terminal shell.  But like, you don't want to be doing that every   single time. You also don't want to be doing that  manually, every single time. So we're gonna write   a test for it, they'll automatically test it for  us. Okay, cool. So now we're going to go into our   test file and write this code and then I'll kind  of break it down. So in our under our polls app,   we're going to go into our tests and we will paste  this guy here. Okay, I copied over everything   and I pasted it over it. So what's going on?  we're importing date time, just like we did in   the shell. we're importing timezone nor importing  test case. And we're importing the question model   from our models. And how is this working? The  class is we're calling a question model tests.   So the good idea is like, every time you want to  test, a model, make a class for that test. Ok.   So this way, it's nice and organized. This class  inherits from test case that's coming from here,   you kind of put that in without really thinking  about it. Okay, just like, look at the Django   Doc's is saying, and just like follow it all  along, it's not necessary for you to like, learn   about this test case class and how it's being  inherited and like, get a PhD in it, you can,   but it's not necessary. And then, for a year,  the name of the function that you're testing,   you want to a good practice, you want to like  break each thing you're testing have a function   for that particularly, right. So for example, if  I go into my models, I have a method called was   published recently. So since we want to test that  specific method, under that class, look, I'm doing   test was published recently, right? And name,  the test make it pretty specific. So somebody   who's reading your test method, or your test  function should kind of know what it's supposed   to do just from reading the name. So we're testing  was published recently, but with future question,   so what if the question was like, published 30  days in advance? Right? Here's the documentation   for it was published recently returns false for  questions whose publication date is in the future?   Cool. That's what it's supposed to do. Except  it doesn't do that. So now we're checking this,   okay. We're saying, hey, set the time to 30 days  from now, that's what this is doing. And then we   make the future question just from question  class. And then we set the publication date   to that particular time from here, line 16. And  then on line 18. We're just saying, hey, assert,   if this is this, however, this turns to true,  as we saw earlier, right, like right here. So   this is gonna this whole thing, what if you run  it right now is going to turn to true. And that's   really the problem that we're having, right? And  we need to fix that in our tests. We'll expose it,   how do we run our tests, we're just going to go  to our command line. And we're going to do Python   managed up pi test polls. So I'm going to exit  out of this exit. And now I will simply do python   manage.pi. Test polls. So what I'm saying is like  test the polls app, and then it'll automatically   basically run the test.py file inside of the  polls, after you created, run it. And look,   it says failed failures is equal to one. And  basically, it says assertion error, it tried this   line solve that assert is and what it found out  was this was not this. And so it's an assertion   error, and it says true is not false. Now,  if this whole thing evaluated to false,   which is it's supposed to, then it would go false  as false. And then this thing would return true,   and it will throw any errors, okay. Now, as you  have more and more tests in here, all you'll have   to do is just run that once, or you can set up  a web server, it runs that once automatically.   And that way, it'll only alert you if something's  broken. Otherwise, it'll just go silently. That's   the beauty of tests. By the way, have you  guys ever heard the song Fly Me To The Moon,   but I've been in love with it, and I can't stop  thinking about it's like playing in my head, non   stop. Anyways, let's continue. So what happened  is this, Python managed up pi test pulls, looked   for tests in the polls application. And explain  that to already. It found a subclass of the Django   test, a test case, subclass. It created a special  database for the purpose of testing. If I go here,   look, it says destroying test database. So it  created its own database from what was happening   right now. It looks for test methods, ones whose  ones whose names begin with test. Okay, so it's   looking for everything that starts with test.  If you don't have these, starting with tests,   it will find it okay. So like, let's just say it  was like this, and I'll hit save, and then we'll   also run this test polls. And it didn't even find  it. It said ran zero test and zero seconds. But   as soon as I do that, and if I run it, boom, ran.  It created a in tests was published recently with   feature requests, it created a question instance,  whose publication field is 30 days in the future,   right over here. And using the cert is method  discovered. It was published recently returns   true though we want to return false what we found  out here, cool. The test informs us which test   failed and even the line on which the failure  occurred. So here, it'll tell us which line we   failed on line 18. Right? This is line 18. Cool.  So now we're gonna go ahead and fix this bug. How   are we going to fix it? Well, this is the code  that's gonna help us fix it, we already know what   the problem is. amend the method and models up UI.  So it will return true if the date is also in the   past. So we're gonna go into models. And we will  change this to this indentation and whitespace in   Python is important. So make sure it's indented  correctly underneath this was published recently   method. And basically, we're saying, hey, set the  timezone to now like exactly right now and then   subtract one day from now, if that's less than  or equal to the publish, and check if that's   less than or equal to the self published date.  Okay, so if that's less than or equal to the   published date, and then check if self published  date is less than or equal to now. Okay, so in   other words, check that this publication date is  in between this. And this. Does that make sense?   It has to be sandwiched between the two. And run  the test again. So now I'm going to hit save. And   I will simply run the test again. And now look,  it says ran one test. And it gave me an okay,   and it's saying destroying the database. So cool.  It looks like it had no errors. It ran all the   tests successfully. If it showed me something red  or said failures, I know something failed. So now   it's working. Cool. Now we can also do After  identifying a bug, we wrote a test that exposes   it and corrected the bug in the code. So our test  passes. Many other things might go wrong with our   application in the future, but we can be sure that  we want inadvertently reintroduced this bug. So it   will automatically keep checking it and we will  we're not going to be reintroducing this bug,   because we'll always find it because simply  running the tests will warn us immediately,   we can consider this little portion  of the application pin down safely,   forever. Pretty cool. I think that's pretty  freakin cool. And now they're like, Alright, we're   gonna get into some more comprehensive tests.  While we're here, we can further pin down the   was published recently method. In fact, it would  be positively embarrassing if in fixing one bug,   we had introduced another. Cool, add two more test  methods to the same class to test the behavior of   the method more comprehensively. So now we're  going to test was we're going to test the was   published recently method with old question.  And then we're also going to test it with recent   question. And we already have the future question.  So you can only have three cases, future question,   recent question or old question. If a question  is older than one day, it should basically say   that it's not. If the question is older than one  day, it will should return false, it should say   it's not recent. If it's in the future, it should  say it's not recent. If it's been posted less than   one day, then it should say it's recent. So for  example, if we just look at this test code at   a high level, old question, look, it's ask it's  making sure that it's asserting to be false. So   if it's one day and one second ago, right, so if  it's one, if it's exactly one day ago, then what   it should do is it should say yes, it's still  true. But if it's one day and one second ago,   now, I should say it's too late and it should be  considered false. Okay, it should be considered   not recent, and then publish recently with recent  or with recent question. So the question is, as   you can see here, not even one day ago, 23 hours,  59 minutes and 59 seconds ago, almost one day, it   should assert it to be true. Okay. But take these  and we will go into our Our tests, and we will add   this into our tests. Okay? There we go 12341234  and 1234123412341234. Okay, so just make sure that   it's all indented correctly, and then that you  should be good there. So now we have all of those   scenarios covered future old or recent question.  Let's run our test. And let's see if we have any   bugs. No bugs, it looks like our method is working  perfectly. Okay. Just so you understand this code   right here, it will only return true when the  publication date is in between this and that.   Okay, so this is basically saying it's within one  day. And this is saying it's less than now. Okay,   so if this is in between Illa match. And now  we have three tests that confirmed the question   was published recently returned sensible values  for past recent future questions? Good. Again,   polls is a simple application, but however complex  it grows in the future, and whatever other code   interacts with, we now have some guarantee that  the method we have written tests for will behave   in expected ways. Test the view so you can also  test views. The polls application is fairly   undiscriminating, it will publish any question  including ones whose publication date feel lies   in the future, we should improve this setting a  publication date in the future should mean that   the question is published at that moment, but  invisible until then. Alright, so what are we   doing here? Well, when we post our question, if  it's some data in the future, it shouldn't show   it just like for example, on WordPress, if you  publish a blog post for let's say, you know, two   days later, it doesn't show until two days later,  right, you can schedule your post or on YouTube,   sometimes I schedule my videos. And you know, I'll  say real show this video to the audience in one   week from now, right. So if I do show it from one  week from now, it shouldn't be showing it. At that   same time, that would be crazy. That wouldn't make  sense. Just like that. We also want to do with our   questions and make sure that it doesn't just show  out of nowhere. And we want to make a test for a   view. When we fix a bug above, we wrote the test  first and then the code to fix it. In fact, that   was a simple example of test driven development.  But it doesn't really matter in which order we do   the work. In our first test, we focus closely on  the internal behavior of the code for this test,   we want to check its behavior as it would be  experienced by a user through a web browser.   Okay. So the first one, it was like the logic  of the code. This one we're focusing on what   happens if the user is like, testing it, and  the user is actually on the front end of the   website? What does it show to them. And isn't  that cool, so you can automatically test that   every time your code runs, and you don't have  to like go and check if your cart is working,   or your blog is showing things like that. Alright,  so the Django test client, so here's the command,   we're going to go in our command line and type in  so I'm going to copy this guy again. And remember,   we got to do Python, manage that py shell, then  paste this guy, and then we will get set up test   environment just like that. Okay. installed the  template render, which will allow us to blah,   blah, blah, blah, blah, okay. We will get this  guy and then we will also this say something about   timezone, so make sure your timezone is correct.  Mine is in America slash Los Angeles, if I go   in my settings and show you for you, it might be  something different. So you can go in this, go to   this link and look up what your timezone is okay.  So we're going to import the client and then we're   going to create an instance of the client. So here  we're creating an instance. And now we can get a   response from our home page now. When the response  from your home page should give you something like   not found or a 404 it's because if you go to your  home page, there's nothing there right if you just   go to right now your localhost 127 dot o dot o dot  one colon eight And it should give you an error.   The only routes that are mapped is like if you  go to slash admin or if you go to slash polls,   remember that. So that's why the home is giving  us a 404. Right now, we should expect a 404. From   that address. Let's just do response dot status  code. And here it is 404. We should expect to find   something at polls though. Okay, so let's try that  we'll use reverse, rather than a hard coded URL.   So instead of doing like, you know, whatever slash  polls, we're gonna just do a reverse here. Okay,   so from Django, we're gonna import, reverse.  And we'll paste this guy right here. And now,   if we do response, that status code, it shows  me something, if I do response, it's saying,   template response status code is 200. And it's a  text slash HTML file, which it is. Okay, and now   we can also get the content, we can do response  content. So now showing me the content of that   file. And if you remember, we do have a unordered  list in the start. And then we have bullet points.   So here you have what's cracking. in HTML to show  an apostrophe, they have to do this ampersand   number sign, 39, semi colon, that's basically  apostrophe. And we also have another question   what's new, and you can see their links here as  well. Okay. So this is like just showing the code   version of what the user or we actually see on the  front end. And we can also do a response context   and get the latest question list. And look  at give us the questions, what's cracking,   what's new, what's up? Now we can improve our  view as well, the list of Polish, the the list   of poll shows polls that aren't published yet.  Those that have publication date in the future,   let's fix that. So right, that's a problem. So we  need to fix that. We introduced a class based view   based on list view. So we're gonna go ahead and  fix things in there. Now we need to amend it. So   let's go to our views and our index view, we need  to fix this. And changes that also checks the date   by comparing it with the timezone. Now, first, we  need to add an import. So at the top of our code,   we're going to add this here, import timezone.  And then our query set. We're going to change it   a bit. So where is our query set? All right, can  we put this on one line? So it looks slightly less   confusing? Yeah, we're fine. We're not following  Pep eight. We're running across a little bit.   But according to my boy, Raymond, the Oji, heading  anger, or head injure. You know, according to him,   he says 90 to 95 characters should be good enough.  Pepe, I think with the whole 80 character line,   that's kind of stupid. Because, honestly, breaking  this down into new lines, messes up the code   readability. But right now, this looks pretty  easy to read, if you just have it much easier if   you just have it on one line anyway. Okay, what  is it doing? It returns the last five published   questions, not including those set to be published  in the future. All right. So how is it doing that?   It's taking the questions model. It's finding all  the objects and it's filtering those objects and   only finding the following. Okay. This statement  here, it's looking at the publication date,   and it's only finding so this underscore  underscore, lt means you're doing a reverse   search. And you're saying less than or equal to,  that's what LTE means less than or equal to. So   any publication date that was less than or equal  to the current time meaning only past or current   posts, filter those. And then once we find those,  we order those by descending publication date. So   which one was the most recent ones? And then we  show the first five, that's it. Okay. A lot going   on. And now we can also test our new view. So  now you can satisfy yourself that this behaves as   expected by firing up the run server, loading the  site in your browser creating questions with dates   in the past and future and type checking that  only those that have been published are listed.   You don't want to have to do that every single  time you make a change that might affect this.   So let's create a test based on our shell session  above seashells. See, what is it? See She sells   seashells down the seashore. Okay, as a falling  two poles slash test dot p y poles. Alright,   we're adding reverse boom. And we'll create a  shortcut function to create questions as well as a   new test class. So this will create questions for  us. Cool. Since this is not going to be a method   is going to be a function, we're going to put it  outside like that. This will create questions,   how will it create questions, you give it a  question text and you give it days? And then   what it does is it'll create a question Would that  number of days in the future? Or would that number   of days in the past based on whether you pass in a  positive number here, or a negative number here or   something like zero? Okay. Right here, and then it  goes into question that I've just entered creates   that object in questions class. And for the  question, text keyword argument and passes   in question texts, and for the pub date, keyword  argument passes in the time, which it gets from   here. Cool. Cool. Okay, so question view index,  what are we doing there? Question view, question   index view test. So we're creating a new class  here. So I'm going to go right there and paste   it and save. So now we're creating tests for our  index view. Instead of model. Okay, so this is our   model test. And what we're saying is like test no  questions, if no question exists, and appropriate,   and appropriate messages displayed. So if I go  into my views, and you can see, in my views,   let's see, is there is it not there? Or is it an R  h, I think it's in our HTML right index. So here,   you can see it says if there are recent questions  and show them else said, No polls are available.   So we want to test that it actually does  say no polls are available on our front end,   we can actually do that, and right here and we  say, hey, first, check that the status code for   this page is a 200. Meaning that you actually  find this page second test that that response   that you find it contains no polls are available.  Okay, so right now, remember, we have no questions   at the moment. And then also, make sure that  the cert query set is equal to the response   is equal to the following. So this thing? latest  question list should be empty. That makes sense,   right? That means there are no questions, such as  a no polls are available. And it should check that   this is actually just an empty list. Cool. Now,  what we want to do is test past questions. Okay,   again, this could go on, could this go on one  line, or this will be too crazy? This is pretty   crazy. So I can I can break that up a little  bit. That's fine. Still readable for me? Okay,   so we're saying? If we create a question,  okay. Again, this creates its own database,   so it doesn't have our what's cracking and  whatever tests available anymore for these tests,   it creates its own database, and then it destroys  that database afterward. So within this database,   we're creating a question and the question texts  will be called past question instead of what's   cracking or what's poppin or whatever. And we're  gonna say that it should be 30. It should have   been created 30 days ago. Okay, so this is a past  question, hence, test past question. And then what   we're going to say is, hey, response, get that  particular page. And once we get that page, we   want to say, Hey, is the are the latest questions  of that page contain that question? And the answer   will be yes, it does. Because we just created it.  Right here. And if this thing is equal to this,   then the test should pass. We're also going to  create a future question. So this should test   a question 30 days in the future, pretty much  the same thing. And make sure that a response   contains no polls are available. That makes sense,  right? Because if the question is in the future,   then it shouldn't be available right now. So it  should say no polls are available. And also make   sure that the response context latest question is  empty. Because there are no latest questions is   going to be posted in the future. Okay. Cool.  And let's check this guy with the recent and   past questions. Again, think it's a little bit  more readable like that. You can break it down   like this, that should be fine, too. But I like it  like this. And basically, what we're testing here   is that this thing should equal to this thing.  And what's going on here? Are the doc for this   as this is test future question and past question,  even if both past and future questions exist, only   past questions are displayed. That makes sense  to and how does it work? We create a question 30   days in the past, we create a question 30 days in  the future? Question. One is called past question.   Question two is called future question. We get the  polls index page. And then we say that this thing,   the latest question list should only have  the past question those created 30 days ago,   and not the recent question. And it should match  that. And indeed, and it should, right? If we did   everything, right, we shouldn't get an error if we  run this. And then all we need to do is define to   past questions. All right, now this is getting  a little too big. So let's break this one down   now. And you can indent this too. Okay, so what  am I saying here? I'm saying? So test to past   questions. So the questions index page may display  multiple questions. So we also want to see that it   doesn't just display one question. It displays  multiple ones, right? So we have past question,   one, which was created 30 days ago, we have past  question two, which was created five days ago,   we get the polls index page. And then we say make  sure that the question list. Actually, let's do it   like this? Because I think it's more readable,  actually. So you want to say that this should   equal to this? latest question list should have  both of the past questions. Why in this order?   Because remember, the most recent ones it shows  at first, right? If we look at our views, and how   it does it, ascending order, sorry, descending  order, and then the five. So that's why that's   why I would show the past question to first.  And then this one right here. Cool. Basically,   the most recent question and show all the way  at the top. Alright, so first of the question,   shortcut function, create question to take some  repetition? Yeah, well, we pretty much went over   this whole thing. So we don't have to check that  answer. So on in effect, we are using the test to   tell a story of admin input and user experience  on the site and checking that at every state. And   for every new change in the state of the system,  the expected results are published. Now. That's a   really important point, like you're telling a  story with your test guys like this is what's   really important to understand. So if you're  working on a team with somebody and somebody   is reading through your test, they understand  what each of your view is supposed to do,   and what it's supposed to return like so so,  so key, like if I'm looking at somebody's code,   I don't know what the hell it's supposed to  do, right? I don't know what the right answer   is supposed to be. But if I look at their tests,  and they have like bunch of examples, and what   the correct answer and the wrong answer should be  and that these documentation I totally understand   what each function is supposed to do what each  class is supposed to do. And then effectively,   I'm on the same page. And then I can actually  contribute to this project, right, I can go,   that's where you guys hear like, hey, just go  ahead and contribute to open source projects is   one of the ways that you can do that. Understand,  look at their test first. And then, like, I can't   tell you enough, for those of you who are a little  bit more advanced to understand the library,   here's a pro tip, one of the best ways to do it is  not just like, instead of just reading the code,   go and look at their tests, and they will have so  many things in there and what it's supposed to do,   you'll start understanding how this library  supposed to work, and it's how it's supposed   to behave, literally tells a story. Now we want  to test the detail view. Okay. So what we have   works well, however, even though future questions  don't appear in the index, users can still reach   them if they know or guests the right URL. So  we need to add a similar constraint to detail   view. Okay, so we don't want to our users to  be able to reach those questions, obviously,   because they don't exist. So they shouldn't just  be able to go to that particular URL. Okay, like,   let's say you had a blog post, like, whatever  your blog post is called banana. So it's like,   john comm slash blog slash banana. If  you scheduled it for like, a month later,   I shouldn't be able to just go to it from the URL.  Okay, so what's going on here? We have the detail   view. So let's go into our views. Let's go into  our detail view. It's right here. What do they   want us to do? They want us to create a query set  and do this with it. Okay, excludes any questions   that aren't published yet. So filter, make sure  the publication date is less than or equal to,   then the time zone now. That's, that's it. That's  essentially it. And those are the only ones you   can check. Pretty cool. Okay. Very, very powerful.  Again, you can see how powerful the generic method   is. And of course, we will add some tests to check  that a question is publication date is in the past   can be displayed, and now one with the publication  date in the future is not. So let's go into our   tests. And let's add the test for this. So again,  it's a new class, it should have its own methods   and everything, right. So for the index view, we  created a class. Okay, for those tests. And now,   for our detail views, we're also creating a class.  Okay, very important. Now we test future question   and we test pass question, how do we do that?  We create the question five days in advance,   we send you to the polls Detail page. So like, for  example, on Instagram, if you click into a image,   and it shows you that specific image that's  equivalent in our app of polls, detail, or   questions, detail view. And for the arguments, we  give it that questions ID from right here. And as   a response, we get that particular URL, and then  we say, hey, make sure that the response actually   returns a 404. And it will, because here's  how we told it. And then test pass question.   So basically, here we're saying 404, meaning  it doesn't exist, right. So the detail view of   a question or the publication date in the past  displays two questions, text. So past question   we create the question here is created five  days ago. We get the URL for the polls detail,   and we pass an ID for the past question. And then  as a response, we get that specific URL. And then   we assert and make sure that it can the response  contains the following thing. So response, and   then it should have the question text in there.  Okay. It's a past question. Question text. Cool.   And, let's see. Let us Let's see if we're gonna be  using any more command line stuff or not. Let's go   an exit. And let's just see right now for tests  are working. In our poll slash views, something's   happening on line 18. What is happening? Ah, oh,  okay, it's not indented correctly, obviously. Save   up and Enter. And look at that all our tests ran  in here. And they all ran successfully. So you can   see all these tests have already gotten pretty  complicated, and they're testing our app pretty   thoroughly. You know, this is not something you  want to do manually every single time, and you   can already see the power of it. Alright, ideas  for more tests. So we got to add similar query   set method to results view and create a new test  class for that view. So we can also test results   view. It'll be very similar to what we have just  created. In fact, there'll be a lot of repetition,   we could also improve our application and other  ways adding tests along the way, for example, it's   silly that questions can be published on the site  that have no choices. So our views could check   for this and exclude such questions. Our tests  could create a question without choice and then   test that it's not published, as well as create a  similar question with choices and test that it is   published. Also, you can have logged in admin  users who should be allowed to see unpublished   questions, but like ordinary visitors shouldn't  be. So if you're an admin, right, and you have   WordPress blog, and you schedule one in advance,  you can see it but other people can't just like,   I can't schedule my YouTube videos, you can see it  I can. whatever needs to be added to the software   to accomplish this should be accompanied by a test  whether you write the test first and then make the   code pass the test. This is the test driven way  of doing it. Or work out the logic in your code   first, and then write a test to prove it. At a  certain point, you're bound to look at your test   and wonder whether your code is suffering from  test bloat, which brings us to the following.   So the thing that they say is when testing more  is actually better. Okay. So it might seem that   your test is going out of control. And there's a  lot of like test bloat. And you know what? Your   beautiful, elegant and concise code compared to  your tests looks so much better. That's totally   okay. Tests are supposed to be bulky and a  lot. And they should cover your ass. Okay,   that's their job. And so they don't have to look  pretty, they don't have to look beautiful, they   have to tell a story and have to tell it clearly.  So it doesn't matter. Right? let them grow. And   for the most part, you can write a test once and  then forget about it, it will continue performing   its useful function. As you continue to develop  your program. Sometimes they will need to be   updated just like we had to update ours, telling  us exactly which test needs to be amended to bring   up to date so that extent, tests help look after  themselves. At worst, as you continue developing,   you might find that you have some tests that are  redundant. In testing redundancy is actually a   good thing. And even that redundancy is not a  problem. Okay? So the more you test, the better   and you don't have to go back and wipe anything  clean. As long as they're sensibly arranged,   they won't become unmanageable, okay? So the good  rules of thumbs. Good rules of thumb include the   following. You should have a separate test class  for each model or view. So for remember, for each   of our models, right, or question model, question  model test, we had a different class for this. And   for each of our views, we actually had a different  class for a detail view, we had a different class   for our index view. And if you wanted to go  further, we could also add a different class for   our results view. A separate test method for each  set of conditions you want to test. So instead of   testing test, no questions has passed question and  kind of like testing an all in one, it's a good   idea to break it down into separate different  tests. Each test doing only one job so here   if no questions exist, and appropriate message  displayed, that's what this is. Test is supposed   to do. This test over here. Questions with the  publication date in the past are displayed on   this page. Like you can see each each test is  trying to do one and one thing only. Okay. test   method names that describe their functions. So the  names themselves should describe the function of   the test. Okay, so test no questions, test pass  questions, test future questions. And once you   build this naming convention, you and your team  starts understanding it. And most of the times,   you guys will be able to just look at each other  tests and know what your app is supposed to be   doing, or it's not supposed to be doing. further  testing, this tutorial only introduces some of the   basics of testing, there's a great deal more that  you can do and a number of very useful tools at   your disposal to achieve some very clever things.  For example, so this is a pretty cool part. Right   now, we just kind of tested our back end and  a little bit of our front end. But what if we   wanted to test our JavaScript and how it loads and  literally, like, moving the mouse, like have the   computer, move the mouse and select one of the  votes and click vote? How does that experience   work? How can we test that on autopilot? where  it happens automatically? Well, there's something   called selenium, selenium, or Selenium. And  it's a way to test your HTML actually renders   in a browser. Okay. So these tools allow you to  check not just the behavior of your Django code,   but also, for example of your JavaScript and your  browser, pretty freaking mind blowing. It's quite   something to see the tests, launch a browser and  start interacting with your site as if a human   being were driving it. And Django includes live  server testcase, to facilitate integration with   tools like selenium, okay, so if you want to get  more advanced, look up Django and selenium. And   you can even look up YouTube videos online and  add those kinds of tests within your app. If   you have a complex application, you may want to  run tests automatically with every commit for   the purposes of continuous integration. So if you  guys know about GitHub, and commits, you can make   it so that when you're writing the code, and as  soon as you commit it, I like to call it like the   time machine, because that's what Git and version  control allows you to do. You can make it so then   it tests it on every commit. So that if any one  of your commits, you know fails any of the tests,   it'll be like, Hey, this is broken. And you'll  find out right away, before you actually push   that code onto GitHub, and destroy your life,  embarrass yourself, Let down your family and be   fired from your job. So that quality control  it is itself at least partially automated,   a good way, a good way to spot untested parts of  your application is to check code coverage. This   also helps identify fragile or even dead  code. If you can't test a piece of code,   it usually means that code should be refactored or  removed. that's those are some big words. coverage   will help to identify dead code c integration  coverage dot p y. And you can check you know   what's dead code and what's not. And, yeah, so  a lot of testing, I hope that you enjoyed that.   We're going to be covering essentially how static  files work in Jango. Okay, and how you can use   them to customize your apps look and feel. Okay,  so without any further ado, let's jump right into   it. Okay, so writing your first app, Part Six,  right? So how are what are we doing now? Now   we've built a tested web poll application. If you  haven't done that, go back to part five. If you   haven't done part five, go back to Part Part Four.  Make sure you're following this in order. And now   will now add a stylesheet and an image. Okay. So  aside from HTML that your app generates, right,   and shows which is your front end, so far, the  voting thing that we have, or it shows some text   with radio buttons, your website needs to be able  to do other things to like show people images,   or pictures of cats or blog post images. It also  needs to be able to serve up JavaScript if you   have any JavaScript, right? So for example, if  you don't know what JavaScript is, is totally   fine. But like, anytime you're clicking a button,  and it like pops up a menu kind of thing. That's   usually JavaScript going on there. Okay. If  you click something like a pop up comes up,   there's JavaScript, JavaScript is pretty much  everywhere. So your website needs to be able   to show some JavaScript and it also needs  to be able to serve CSS, okay, which is,   it's called CAS stands for cascading style sheet  and you use this to stylize your app and make it   look cool and beautiful. Okay. And yeah, so  that's usually what's necessary to complete   a web page. In Django. We refer to these files as  static files. Now for small projects, right? This   isn't a big deal, because you can just keep the  static file somewhere where your web server can   find it. However, in bigger projects, especially  those comprise of like multiple attributes,   if you have multiple apps like polls and blog,  and e commerce, like whatever, dealing with   the multiple sets of static files provided by  each application starts to get tricky. That's   why Django contrib that static files is there for  you, if you're a beginner, don't worry about this   part too much. But this is for more advanced  people mentioning this part, okay? Otherwise,   I've kind of skipped over. It collects static  files from each of your applications and any other   places you specify into a single location that can  be that can easily be served in production. Okay,   so now let's get to customizing your app's look  and feel. So first, we're going to need to create   a directory called static in your polls directory.  Okay, so let's go ahead and do that. And I   will open up, Adam, and we will go in our polls.  Hopefully, you can see that on the left hand side,   I don't know how to make tab bigger. So I'm  sorry about that. But yeah, we're gonna go   inside of our polls, and inside of our polls,  I think this is where it wants us to make it.   So I'm going to right click this polls, not the  templates one. So right click, right click here,   create a new folder and call it static. Done.  Okay, cool. And for those of you wondering, like,   how do I switch like that it's command and tab,  and on Windows, that's all done tab. Cool. Django   will look for static files. They're similarly  to how Django finds templates inside polls,   template polls slash templates. So you know how  there's like polls slash templates, and Django   automatically looks for templates there. Well,  just like that, for your static files, Django   is going to look inside of your folder static.  Okay, so Django static file setting contains a   list of finders that know how to discover static  files from various sources. One of the defaults   is AB directories finder, which looks for a static  subdirectory in each of the installed apps, okay,   so Django will automatically look for a folder  called static under each of the installed apps.   Okay, so right now, we have polls as one of our  apps that we created. And remember to install   this app, we had to do this line in our settings  file under installed apps. And then, now Django   is able to find its static folder. If you have  another app, again, like a blog app, and you have   static folder under there and you install the blog  app, then you'll be able to then Django will be   able to find the blogs, blog apps, static files,  okay, like images, JavaScript, CSS, those are all   considered static files. All right, the admin uses  the same directory structure for its static files.   Cool. So admin site works the same way. Within  the static directory, you've just created creating   another directory called polls. So inside of  static, we're going to create another directory,   and we're going to call it polls, okay? So kind of  like how you have polls, templates, polls, you're   gonna have polls, static polls, okay, similar. And  then inside of here, we're going to create a file   called styles dot CSS, I'm going to do new file,  and I'll do style dot CSS, just like that. Okay,   so this is our CSS. Again, in the command line,  if you haven't activated your virtual environment,   make sure to do conda or sorry, source, activate  my sites. If you haven't done that, just in case   you need to do something in the command line,  which you're not going to in this video i don't   think because of how the app directories find  your static files. Find your works you can refer   to this data file and Django simply as polls slash  styles dot CSS similar to how you reference a path   for templates. So remember how for templates  you just go pole slash index dot HTML well   for this is pole slash style dot CSS, okay. And  for namespacing it's just like templates. So the   same reason why you put templates under the same  reason why you make a new folder called polls,   under templates is the same reason why you create  another folder called polls under static it so   then if you have multiple different apps, there  is no collision based on like you having the same   name for any of your CSS files or any of your HTML  Mel files. That's what they're saying here. Okay,   now we're gonna do some fun CSS stuff, okay,  and we're going to keep it pretty simple. So   in our style dot CSS, what I'm basically saying is  that any link tag under a bullet point are listed   thing, color red and green. Okay? So A stands for  is like your link tags, anything that contains a   link, basically returning for now returning almost  all of our links on our current site green. Next,   add the following at the top of polls, slash  templates, slash polls slash index dot HTML. So   we're going to go in our templates polls index  dot HTML, and at the top we're going to add is   we're going to say load static. So we're going to  add that right here, load static. So what this is   not able to do is load our static files. And  then right here, I'm going to add this. So I'm   creating, I'm creating a link to a stylesheet. The  type is text slash CSS. And the link is this. Now   I'm using the link in a dynamic way. This is  the best way to link it instead of like hard   coding natural path. And you just say Polo slash  style dot CSS, okay, that's how we refer to it.   And that's pretty much it. Okay, so now, let's  go to our, our website. So I'm gonna do Python,   manage that py run server. And we're gonna  open up a new tab, and I'm going to go 127   that slash 1000. Or I'm sorry, slash polls.  And you can see that all the links are green,   right, if I go back to my stylesheet, and turn it  into something else. So let's go back into sorry,   style that CSS is right there, I'll bring it  here. If I change this to like blue, save,   Command S go back here refresh, you can see that  all of this is now blue. If your didn't turn blue,   close out of your server, or break the server with  Ctrl C, and then try it again and then should be   fixed. And Yep, there we go. And also make sure to  save Okay, and another way to go to this same link   is doing HTTP localhost colon 8000. Slash polls,  okay. And that should take you to localhost colon   8000 slash pauses the same thing as your  127 dot o dot o dot one colon 8000. Do the   same thing. Alright, so that's essentially how  we got that to work. Bring this guy here. Now,   we also can add a background image. Okay, so we'll  create a subdirectory for images create an images   subdirectory. So basically, inside of our static,  and polls, we're going to create static holes,   we're going to create a new directory, and we're  going to call it images. This is where we're   going to put all up all of our images. So it  should look like this. And then you can put   whatever image you want, right background dot GIF,  or. So what we'll do is we'll go online and like,   grab an image. So let's get cats. Right click,  and then just save the image. And you can save   it whatever you I'm going to call it like  cat back round. Oh, sorry, we can just save   it wherever we want. I'm going to save it under  my site, my site, or sorry, polls, static polls,   images, and I'm going to save this cat underscore  background. And it's automatically dot JPG file.   Because I have the format selected like that. I'm  going to hit save. It saved I'm going to open up   my atom. And under images, I now have my cat  background JPEG. So let's go back to this   tutorial. And it's basically saying to do this,  add this to your style sheet. So I'm going to add   this now, I'm going to say so from images  instead of background that GIF mine is called   cat underscore background dot jpg, like that. So  now, it's gonna find basically in our HTML code,   it's going to find anywhere we have the body tag,  it's gonna make its background, this cat image,   okay, so if I go to, you know, our index dot  HTML, if any of this stuff is In a body tag,   it'll add that to the background. So let's check  it out. It says, and you should see the background   loaded in the top left of the screen. Okay, let's  give it a try. Let's see if they're in line. And   there you go. It's there, right? So pretty cool  how it works. And what I could also do is I could   go to my index dot HTML, and like wrap maybe  a certain part of it in the body tag. So like,   maybe the part that's in the for loop, right? So  I can, I can go like, body tag. And I can choose   to close the body tag outside of this unordered  list, I can go body like that. Okay, if I want to,   and I go back, I refresh. And the same thing.  Okay. So this is essentially like a little bit   of how HTML and CSS like talk with each other.  Okay, and now let's look at kind of their last   notes here. So there, okay, so warning, of course,  the static template tag is not available for use   in static files, like your style sheet, which  aren't generated by Django. So in your CSS file,   you can't use something like, static. Like that.  It's not going to know what that is. And you can   do like if then statements here. These are just  your static files, hence, they're not dynamic and   can't do like variables and cool stuff, right?  Like your index, your HTML file can with the,   which has a Django templating. system. And in  there, you should always use relative paths.   So here, we're not using like, slash user slash  clever programmers slash GitHub, slash my site,   slash my site or slash polls, slash what else is  it? static slash polls slash images, right, we're   not using the absolute path. That's the definition  of absolute path, we're using a relative path to   it. Do you're satisfied between each other because  then you can change static underscore URL. So this   is again, a little bit more advanced. I'm gonna  I'm gonna skip over this one. But you can read   that if you want. And that's essentially how you  work with general like static files on Django.   There you have it, folks, I hope you enjoyed this  tutorial. I hope it was informative, and juicy,   and you loved it. If you did love it, please leave  a comment, please like it and share it with at   least one friend. Because if you have at least one  friend or family member, sorry, what's happening   in my mind, if you have one friend or one family  member who's doing development alongside you,   is going to boost your success rate up by at least  60%. They have like scientific studies on this. So   share it, maybe somebody will watch it alongside  and you will become web developers together.
Info
Channel: freeCodeCamp.org
Views: 212,946
Rating: undefined out of 5
Keywords: django, python django, django tutorial, django course, python django course for beginners, django 2.0 tutorial, django docs, python django tutorial, django framework, python django course, python django framework
Id: cI3FOYIMSYE
Channel Id: undefined
Length: 213min 21sec (12801 seconds)
Published: Fri Aug 03 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.