Python Django Tutorial 2018 for Beginners Part 4 - Generic Forms & Views

Django Generic Views: Displaying Lists and Details with Ease

In this tutorial, we will explore Django's generic views, specifically the list view and detail view. These two views abstract the concept of displaying a list of objects and a single object's details, respectively. By using generic views, we can simplify our code and make it more efficient.

The List View

-------------

A generic view needs to know what model it will be acting upon. In this case, we are using the `Question` model. The `List` view is responsible for displaying a list of objects that match the specified criteria. To use the `List` view, we need to define a template name. In our case, we have created a template called `app_name slash model_name underscore list.html`. This template will be used to display the list of questions.

When using the `List` view, we can override the context variables by specifying a custom object as the `object_name` attribute. For example, if we want to display a list of choices instead of questions, we would use the `question__list` variable. By providing this custom variable, we can access it in our templates using the dot notation.

The Detail View

----------------

A generic view expects a primary key value captured from the URL to be called `pk`. This is why we need to specify the `pk` parameter when creating a detail view. The `Detail` view is responsible for displaying a single object's details.

In our case, we are using the `Question` model again. We have created a template called `app_name slash model_name underscore detailed.html`, which will be used to display each question's details. This template uses a default name, but we can override it by specifying a custom template name when creating the view.

When using the `Detail` view, Django automatically provides the object instance as an attribute of the context dictionary. In our case, this means that the `question` variable is provided automatically. However, if we want to access other attributes of the question instance, such as its score or latest answer, we can use the dot notation.

Using Generic Views in Our App

-----------------------------

To put it all together, let's create a view that uses both the `List` and `Detail` views. We will create an `index` view that displays a list of questions, along with their details. This view will use the `question__list` variable to access the list of choices for each question.

Here is an example of how we might define this view:

```python

from django.views.generic import ListView, DetailView

class IndexView(ListView):

model = Question

template_name = 'app_name/question_list.html'

context_object_name = 'question_list'

class QuestionDetailView(DetailView):

model = Question

pk_url_kwarg = 'pk'

template_name = 'app_name/question_detailed.html'

```

In our templates, we can use the dot notation to access the object instance and its attributes. For example, in our `question_list.html` template, we can use `{{ question.score }}` to display the score of each question.

Conclusion

----------

In this tutorial, we have explored Django's generic views, specifically the list view and detail view. By using these views, we can simplify our code and make it more efficient. We have also learned how to override context variables and access object instances using the dot notation. With these skills, you will be well on your way to becoming a proficient Django developer.

The Polling App

----------------

To illustrate the use of generic views in a real-world application, let's create a simple polling app. In this app, we will have a list view that displays a list of questions, along with their details. Each question will have a score and a list of choices. When a user votes for a question, it will be updated on the server.

Here is an example of how our polling app might look:

```html

Polls

    {% for question in question_list %}

  • {{ question.question }}

      {% for choice in question.choice_set.all %}

    • {{ choice.choice }}
    • {% endfor %}

  • {% endfor %}

{% csrf_token %}

{{ form.as_p }}

```

In our code, we would create a view that uses the `List` and `Detail` views to display the list of questions and their details. We would also create forms to handle user input and update the question scores.

The Profitable Programmer Course

--------------------------------

If you're serious about web development and want to take your skills to the next level, we recommend checking out our course called "The Profitable Programmer." This course will teach you how to become a badass at Django development and create profitable online applications.

"WEBVTTKind: captionsLanguage: enhey guys what's up how's it going this is Kazi from clever programmer calm welcome back to another episode with writing your first jingo app part 4 following the official jingo documentation so let's continue and kick ass alright so we're continuing a web poll application and it will focus on simple processing simple form processing and cutting down our code so the big things we're gonna be doing is how do you add a form that where you can submit information to so basically it's gonna be a form it's gonna have radio buttons you're gonna pick your choice you're gonna click on it and then you're gonna be able to send that data over that's number one big thing we're gonna be doing the second big thing we're gonna be doing is cutting down our code using something called Django's a generic views they 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 gonna cop this guy and then I'm gonna break it down to you you my friend should not be copying your learning this stuff you should be writing this down line by line and going hmm how does this work ah that's how it works Oh huh 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 gonna 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 detailed HTML and we're gonna put this over that okay so what is going on at a higher level we have a for our heading 1 so this is where what the specific question is okay so what's up what's cracking what's popping things like that right here this line is saying hey man look if there 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 edge one tax it's just HTML here is a little bit of Django going on so here we're saying if there are there is an error message and then show it okay and show it covered in strong tax so it looks nice and then here's where we're creating a form so we start the form tag here and end 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 the information where they're previously added shoes to their cart and then shows the shoes and the shirt and the tie on the Pursey to checkout page okay that's essentially how you use forms in real life okay so here we have it - 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 mention it cross-site request forgery zou kay 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 our question choice is well remember each so you have question and then one question can have multiple answers to it those answers are the things that yet I've voted on so what we're doing now is listing out all of those answers or those or those choices and and and and I'll show you right now how it'll 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 say I click on what's cracking and you can see it says what's cracking followed by vote right underneath it okay let's go - 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 gonna 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 could pick whichever one you want that's it and then you hit vote boom okay you're voting on question one it 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 just using the built-in Django template in systems for loop counter so I'll give the ID one-two-three-four as it's looping through and yeah value is 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 it calls with that so here we're saying call it vote and then for type we're gonna say it's a submit button so the type we're just gonna give a 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 we'll send the post data choice where a number is the ID of the selected choice this is 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 requests 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 could get screwed okay so simply put as opposed to yet it's very important because the act of submitting this form will alter data server-side whenever you create a form that alters our data server-side use method post' this tip isn't specifically Django is just good web development practice for loop counter indicates how many times the 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 create a Django view that handles and submitted data and does something with it or remember in tutorial 3 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 URL stop py you'll see four votes I have this line right over here and so should you alright now let's add the now that we're gonna create a real version for our vote so up until now we had a functionality for a 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 will need HTTP response redirects 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 gonna add that in and hit save and then that's essentially essentially and then it except we're gonna have a choice right here safe 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 a 404 error we then get the answers for that particular question okay or select a choice one specific choice that's what we get okay so for example whether the choice is gonna be the sky or whether the choice is gonna be something else right it's not going to show it to me right now because the app is offline right now the server is closed but since we had two choices and you could vote for this choice or this choice how are you gonna know which one is sent right so that's what we're trying to pick here which ever choice you select the radio button next to that's whose primary key we're gonna be passing in and how we get that is request that post choice request that 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 AHA 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 I should say vote here now when I hit the sky we're gonna see what happened so I'm gonna hit inspect here and our console pops up right we're gonna go to sources console is looking pretty insane right now but that's fine I'm gonna click on network and we're gonna click vote so we're just voted for this guy okay now in our network let's see if we can zoom out a little bit because it's a little too crazy all right so in our network we can see that the requests Methodist 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 in results it's showing me or 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 Kier and in the case that the choice does not exist we return polls slash detailed HTML we render that and we return that question object and for our error message we say that you didn't select a choice okay so if you somehow it's selected you know nothing and otherwise if we have selected it and we haven't ran into this issue what we want to say is for that particular choice we want to upload it by one so we're incrementing the vote count by one we want to save it and then we redirect okay so we're gonna 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 the sky let's click vote so you can see okay so that's that's exactly what I needed here it's 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 the important part and it also has a CSRF middleware token which remember we did CSRF underscore token that's where it's generating that from but the choice is the most important one so whether it was choice one or is chose 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 a value to something like a 1 or something like a 2 this whole thing evaluates to that specific question object and then we up vote it 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 a render the home page because if the user refreshes it'll 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 resubmit three thousand and three thousand dollars again you're gonna run out of money pretty fast right nine thousand dollars 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 she to 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 happens 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 gonna go in Python manage that py shell so we're gonna do is from polls that models I'm gonna import choice and I'm also gonna do from polls dot models import question question dot objects dot get let's say we want to get our first question or whatsup question and we're gonna 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 sky one and then for the sky one we can see it's vote count in models I forget what is the vote or is it votes so you can see that it has two votes and then the other one there's one 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 Q dot choice says and again like I've mentioned in our four at the end of our first video like if you want to change that I'm not gonna change it now just to stay consistent with Django's official Docs but essentially like right in here right right on 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 Joyce says okay something like that but we're not gonna do it right now we're gonna stick to a Django's name because otherwise I'll have to make migrations and things like that everything is fine for now I'm gonna 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 all right let's see what they're saying here request that post is a dictionary like object lets you access submitted data by key name yep so that's how we we use a choice key name requests at post values are always strings cool note that jingle also provides requests I get that's by default that's there but we're explicitly using requests our post and our code to ensure that data is only altered via post call we'll raise a cure if choice wasn't provided and post a dub dub of code checks for Kiara right over here Andrey displays 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 see 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 gonna write it okay so here is what it should be looking like let's check our results just pop that bad boy whoops pop that boy right in here and we just say get that particular question or other Westerwelle 404 and once you get it take me to and once you get that question take me to Roselle's dot HTML so you can already see there are some similarities right like here there's a similarity and here 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 detailed view for both of them but in one you're sending me to detail that HTML on the other one you're selling sending me two results at 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 detailed view from tutorial three the only difference is a template name will fix this redundancy later so they mentioned that now let's create a pole slash results dot HTML so we're gonna go in and create new file I'm gonna call it resolves dot HTML just like that I'll paste it here and we'll go to our app and will vote for the sky and then it'll take us to the results of what's up and look at that not much it says two votes on 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 that we've 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's 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 a 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 pluralize and then PluralEyes will be like hey yes you should pluralize it and put an S here and then I'll put like an ass like that okay cool would that said that ends a four 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 detailed 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 in a 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 and let's check out now go to poll 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 wanted 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 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 view 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 a 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 Jango has something called generic views these are class-based views that essentially have you once you use them you don't have to write that much real code it just does a lot of the things auto magically in a pretty intelligent way so I like this and check it out all right the detail and results views are very simple as mentioned above but they're redundant okay the index view which displays a list of polls 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 said 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 you don't even need to write Python code to write an app you can 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 1 convert the URL conf delete some of the old unneeded views and introduce new views based on generics generic Chango views all right 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 are doing your app you already know how 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 even can do basic 2+2 or in my case in one of my videos I think I had to do 2,000 divided by 10 on a calculator that was a pretty sad moment and that has a lot of upvotes it 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 Jango generic views comes pretty close so let's keep going all right amend URL Conte first open the pull slash URLs that py you're on conned then change it like so so we're gonna go in pull /url s dot py and I'm just gonna 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 it's changed before it was just dot index now it's index view dot as view detail view as view results view dot as view and those are the middle arguments that change right what are the other arguments that change 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 peek hey everywhere if you notice right so that's another big change to keep in the back of your 4head all right that's what they mentioned over here cool so that's essentially what we're gonna 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 now we need to make changes to our views we're going to remove our old index detail and results views and use Django's generic views instead to do so open them 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 gonna 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'll automatically know which template to use based on this variable these variables are not just random you can't 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 kiemce 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 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 a results view so it's gonna change from this obfuscated looking code to something pretty simple check it out clean right looks a lot cleaner no need for requests 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 gonna 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 on 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 I need to peek here for the generic views but not for the non generic view by default the detailed generic view uses a template called app name slash model name underscore detailed HTML in our case it would use the template the following template right so if I go in my views pull so app name our app name is pulls slash results that 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 detailed view okay similarly the list view generic view uses a default template called similar to the other one we use template name to tell list view 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 as 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 an appropriate 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 list view the 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 Jango to use a 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 gonna 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 alright so that's it for a django tutorial part 5 I hope that you found it informative I hope that you found it fascinating it awesome I'm glad you're enjoying this so far we do have a new course coming up called the profitable programmer so if you're serious about your web development you want to take it to the next level you want to become badass at Django you want to learn how to get clients you want to learn how to become a freelance web developer in less than 90 days you want to create apps and do all these things right you want a deep dive perfect this is the course for you go to this link ok put in your email join the VIP wait it's absolutely free I'll give you I'll let you download your Python earning potential calculator for absolutely free as my gift to you and then when this course opens up you will be the first to know about it ok that's it for this video thank you so much for watching as always I loved your faces off and I'll see you in the next videohey guys what's up how's it going this is Kazi from clever programmer calm welcome back to another episode with writing your first jingo app part 4 following the official jingo documentation so let's continue and kick ass alright so we're continuing a web poll application and it will focus on simple processing simple form processing and cutting down our code so the big things we're gonna be doing is how do you add a form that where you can submit information to so basically it's gonna be a form it's gonna have radio buttons you're gonna pick your choice you're gonna click on it and then you're gonna be able to send that data over that's number one big thing we're gonna be doing the second big thing we're gonna be doing is cutting down our code using something called Django's a generic views they 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 gonna cop this guy and then I'm gonna break it down to you you my friend should not be copying your learning this stuff you should be writing this down line by line and going hmm how does this work ah that's how it works Oh huh 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 gonna 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 detailed HTML and we're gonna put this over that okay so what is going on at a higher level we have a for our heading 1 so this is where what the specific question is okay so what's up what's cracking what's popping things like that right here this line is saying hey man look if there 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 edge one tax it's just HTML here is a little bit of Django going on so here we're saying if there are there is an error message and then show it okay and show it covered in strong tax so it looks nice and then here's where we're creating a form so we start the form tag here and end 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 the information where they're previously added shoes to their cart and then shows the shoes and the shirt and the tie on the Pursey to checkout page okay that's essentially how you use forms in real life okay so here we have it - 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 mention it cross-site request forgery zou kay 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 our question choice is well remember each so you have question and then one question can have multiple answers to it those answers are the things that yet I've voted on so what we're doing now is listing out all of those answers or those or those choices and and and and I'll show you right now how it'll 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 say I click on what's cracking and you can see it says what's cracking followed by vote right underneath it okay let's go - 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 gonna 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 could pick whichever one you want that's it and then you hit vote boom okay you're voting on question one it 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 just using the built-in Django template in systems for loop counter so I'll give the ID one-two-three-four as it's looping through and yeah value is 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 it calls with that so here we're saying call it vote and then for type we're gonna say it's a submit button so the type we're just gonna give a 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 we'll send the post data choice where a number is the ID of the selected choice this is 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 requests 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 could get screwed okay so simply put as opposed to yet it's very important because the act of submitting this form will alter data server-side whenever you create a form that alters our data server-side use method post' this tip isn't specifically Django is just good web development practice for loop counter indicates how many times the 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 create a Django view that handles and submitted data and does something with it or remember in tutorial 3 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 URL stop py you'll see four votes I have this line right over here and so should you alright now let's add the now that we're gonna create a real version for our vote so up until now we had a functionality for a 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 will need HTTP response redirects 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 gonna add that in and hit save and then that's essentially essentially and then it except we're gonna have a choice right here safe 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 a 404 error we then get the answers for that particular question okay or select a choice one specific choice that's what we get okay so for example whether the choice is gonna be the sky or whether the choice is gonna be something else right it's not going to show it to me right now because the app is offline right now the server is closed but since we had two choices and you could vote for this choice or this choice how are you gonna know which one is sent right so that's what we're trying to pick here which ever choice you select the radio button next to that's whose primary key we're gonna be passing in and how we get that is request that post choice request that 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 AHA 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 I should say vote here now when I hit the sky we're gonna see what happened so I'm gonna hit inspect here and our console pops up right we're gonna go to sources console is looking pretty insane right now but that's fine I'm gonna click on network and we're gonna click vote so we're just voted for this guy okay now in our network let's see if we can zoom out a little bit because it's a little too crazy all right so in our network we can see that the requests Methodist 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 in results it's showing me or 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 Kier and in the case that the choice does not exist we return polls slash detailed HTML we render that and we return that question object and for our error message we say that you didn't select a choice okay so if you somehow it's selected you know nothing and otherwise if we have selected it and we haven't ran into this issue what we want to say is for that particular choice we want to upload it by one so we're incrementing the vote count by one we want to save it and then we redirect okay so we're gonna 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 the sky let's click vote so you can see okay so that's that's exactly what I needed here it's 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 the important part and it also has a CSRF middleware token which remember we did CSRF underscore token that's where it's generating that from but the choice is the most important one so whether it was choice one or is chose 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 a value to something like a 1 or something like a 2 this whole thing evaluates to that specific question object and then we up vote it 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 a render the home page because if the user refreshes it'll 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 resubmit three thousand and three thousand dollars again you're gonna run out of money pretty fast right nine thousand dollars 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 she to 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 happens 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 gonna go in Python manage that py shell so we're gonna do is from polls that models I'm gonna import choice and I'm also gonna do from polls dot models import question question dot objects dot get let's say we want to get our first question or whatsup question and we're gonna 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 sky one and then for the sky one we can see it's vote count in models I forget what is the vote or is it votes so you can see that it has two votes and then the other one there's one 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 Q dot choice says and again like I've mentioned in our four at the end of our first video like if you want to change that I'm not gonna change it now just to stay consistent with Django's official Docs but essentially like right in here right right on 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 Joyce says okay something like that but we're not gonna do it right now we're gonna stick to a Django's name because otherwise I'll have to make migrations and things like that everything is fine for now I'm gonna 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 all right let's see what they're saying here request that post is a dictionary like object lets you access submitted data by key name yep so that's how we we use a choice key name requests at post values are always strings cool note that jingle also provides requests I get that's by default that's there but we're explicitly using requests our post and our code to ensure that data is only altered via post call we'll raise a cure if choice wasn't provided and post a dub dub of code checks for Kiara right over here Andrey displays 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 see 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 gonna write it okay so here is what it should be looking like let's check our results just pop that bad boy whoops pop that boy right in here and we just say get that particular question or other Westerwelle 404 and once you get it take me to and once you get that question take me to Roselle's dot HTML so you can already see there are some similarities right like here there's a similarity and here 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 detailed view for both of them but in one you're sending me to detail that HTML on the other one you're selling sending me two results at 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 detailed view from tutorial three the only difference is a template name will fix this redundancy later so they mentioned that now let's create a pole slash results dot HTML so we're gonna go in and create new file I'm gonna call it resolves dot HTML just like that I'll paste it here and we'll go to our app and will vote for the sky and then it'll take us to the results of what's up and look at that not much it says two votes on 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 that we've 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's 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 a 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 pluralize and then PluralEyes will be like hey yes you should pluralize it and put an S here and then I'll put like an ass like that okay cool would that said that ends a four 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 detailed 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 in a 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 and let's check out now go to poll 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 wanted 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 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 view 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 a 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 Jango has something called generic views these are class-based views that essentially have you once you use them you don't have to write that much real code it just does a lot of the things auto magically in a pretty intelligent way so I like this and check it out all right the detail and results views are very simple as mentioned above but they're redundant okay the index view which displays a list of polls 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 said 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 you don't even need to write Python code to write an app you can 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 1 convert the URL conf delete some of the old unneeded views and introduce new views based on generics generic Chango views all right 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 are doing your app you already know how 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 even can do basic 2+2 or in my case in one of my videos I think I had to do 2,000 divided by 10 on a calculator that was a pretty sad moment and that has a lot of upvotes it 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 Jango generic views comes pretty close so let's keep going all right amend URL Conte first open the pull slash URLs that py you're on conned then change it like so so we're gonna go in pull /url s dot py and I'm just gonna 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 it's changed before it was just dot index now it's index view dot as view detail view as view results view dot as view and those are the middle arguments that change right what are the other arguments that change 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 peek hey everywhere if you notice right so that's another big change to keep in the back of your 4head all right that's what they mentioned over here cool so that's essentially what we're gonna 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 now we need to make changes to our views we're going to remove our old index detail and results views and use Django's generic views instead to do so open them 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 gonna 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'll automatically know which template to use based on this variable these variables are not just random you can't 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 kiemce 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 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 a results view so it's gonna change from this obfuscated looking code to something pretty simple check it out clean right looks a lot cleaner no need for requests 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 gonna 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 on 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 I need to peek here for the generic views but not for the non generic view by default the detailed generic view uses a template called app name slash model name underscore detailed HTML in our case it would use the template the following template right so if I go in my views pull so app name our app name is pulls slash results that 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 detailed view okay similarly the list view generic view uses a default template called similar to the other one we use template name to tell list view 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 as 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 an appropriate 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 list view the 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 Jango to use a 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 gonna 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 alright so that's it for a django tutorial part 5 I hope that you found it informative I hope that you found it fascinating it awesome I'm glad you're enjoying this so far we do have a new course coming up called the profitable programmer so if you're serious about your web development you want to take it to the next level you want to become badass at Django you want to learn how to get clients you want to learn how to become a freelance web developer in less than 90 days you want to create apps and do all these things right you want a deep dive perfect this is the course for you go to this link ok put in your email join the VIP wait it's absolutely free I'll give you I'll let you download your Python earning potential calculator for absolutely free as my gift to you and then when this course opens up you will be the first to know about it ok that's it for this video thank you so much for watching as always I loved your faces off and I'll see you in the next video\n"