Formsets9:23 with Kenneth Love
Quite often, it's really handy to be able to create or edit multiple instances of a model all at once. Formsets let us do that.
[MUSIC] 0:00 Right now our mini CMS isn't the most usable thing ever. 0:04 I mean, we can make quizzes and questions and answers and 0:08 all of that, we just have to go to a bunch of different pages and 0:11 remember orders and all sorts of things we shouldn't have to remember. 0:14 Let's start with giving ourselves more forms on a single view so 0:18 that we can make multiple items at once. 0:21 So, right now if we wanna add answers to a question we have to go edit the questions, 0:25 and then we have to hit add answer, and then we have to add the new answer. 0:32 It's a lot of work, so let's see if we can make this a little bit easier. 0:35 Let's start, we're gonna show more than one form and so 0:41 if I go to django docs and I look down here at forms, 0:46 there's this thing here called Formsets. 0:53 So now by default formsets, just like forms, 0:58 don't work with models, right, they're just for showing regular non-model forms. 1:02 Well, we wanna show model forms. 1:08 Well, luckily, if we scroll down through here just a little bit, 1:09 there's this creating formsets from models with model formsets. 1:13 Cool, that's what we want. 1:18 Thanks django. 1:19 So, we need to make this model formset factory. 1:21 Now these can be a little bit confusing, so 1:23 just stick with me and we'll walk through how to make some of these. 1:26 So in our forms.pie, down here at the bottom, we've got our answer form. 1:30 Let's come down here just a little ways and we're going to make a new form set. 1:37 We're actually gonna make a thing called a formset factory and 1:46 it's a thing, a factory, that makes model formsets. 1:51 Which is why it's called factory. 1:57 But we kind of make it like it's a class, so we're gonna do AnswerFormSet = 2:00 forms.modelformset_factory, there we go. 2:05 And then we have to specify what model the model formset is for. 2:12 So models.Answer, cuz we imported models up here. 2:17 And then we can leave it like that, and it just uses the model. 2:24 But we wanna specify the form that it needs to use. 2:28 So we're gonna say form=AnswerForm, which is that one just up above there. 2:31 Okay, so let's save that and then, let's go over here and 2:38 let's edit our views.py. 2:42 And let's come down here to our answer form. 2:46 Right down here. 2:52 There's a whole lot to this. 2:53 And basically what I want to change is this form bit. 2:56 So we already have a form, let's call it formset. 3:00 And this is gonna be, instead of AnswerForm, it's gonna be AnswerFormSet. 3:05 And then we have to specify, we don't have to, but we want to control 3:10 the answers that show up in our formset, so we set a queryset. 3:15 So the queryset is going to be equal to question, which we got right here, 3:20 .answer_set.all. 3:25 So any answers that are associated with that question, use those as the queryset. 3:27 And, we don't need this answer_pk stuff, 3:34 cuz we're not gonna be editing a single answer. 3:38 We're gonna be editing a bunch of answer, so we'll get rid of the rest of that. 3:40 You know what, I don't have on my indent guides. 3:45 There we go, that's a lot nicer. 3:50 Okay, and then let's actually just take out the rest of our post thing here. 3:52 We're gonna have to clean up a bunch of stuff. 3:57 And instead of form, let's send out the formset, okay. 4:00 So if request.method is equal to POST, then what we wanna do is, 4:05 we want to handle saving all these formset things. 4:12 So first of all we need to rebuild our formset so, forms.AnswerFormSet, 4:19 and we're gonna pass in request.post and we're gonna past in our query set again. 4:24 And that's kinda long so let's push it down there. 4:34 All right. 4:41 And then we can check to make sure the formset is valid. 4:42 So all the forms that are filled out in the formset, make sure they are all valid. 4:46 And if they are, then we're going to make our answers, 4:51 and we're gonna say formset.save. 4:55 Now, we haven't set a question on these answers, so we need to, again, 4:58 do our commit=False, so that we don't have them all just saved automatically. 5:03 And for each answer in answers, 5:10 answer.question = question, and 5:14 then save that answer. 5:19 And then out here let's do messages.success(request, 5:25 and we'll say, "Added answers") and 5:32 then we want to of course return an HTTPResponseRedirect and 5:36 we wanna go the question.quiz.get_absolute_url. 5:43 All right, and if it's not post whatever, 5:50 then we just go right back with our form setting, so we're all good. 5:53 Our view is actually a little bit simpler now, oddly enough. 5:58 All right so let's go to our templates and our answer_form template. 6:03 And we're gonna have to change this up a little bit too. 6:07 So in here, we're 6:13 not gonna have this form.instance.text, we're just gonna have the question. 6:17 So let's just say question and it would be prompt. 6:22 Let's actually just say question. 6:29 We don't need this thing here. 6:33 And we need our quiz, yeah we're good on that, all right. 6:40 And so then here. 6:43 I think we're good too on all of those. 6:47 All right, so that's good. 6:49 So now we're down here into this bit. 6:51 And let's do this so that it puts in the thing correctly, 6:58 div class="row columns". 7:04 And let's indent all of that, and 7:11 inside here, we'll just say, Answers. 7:14 Our form bit here, actually stays the same for the most part, 7:20 we need the csrf_token, and then we're gonna so a section tag. 7:24 And inside that section tag we're gonna print out formset. 7:31 And this will actually loop through and print out all of the form sets for us. 7:34 I'll show you how to handle the rendering of the individual forms later on but 7:41 for now this is good enough. 7:45 All right so let's give it a try. 7:47 If we go here to edit our thing, 7:50 and we go to Add Answer, now we've got multiple answers. 7:53 Let's actually go change a little bit of that. 7:57 Come back over here to our question_form, and 8:01 instead of Add answer, let's just say, Answers. 8:04 Refresh, that'll just say Answers, cool. 8:08 All right, so now in order 0 we have anything that's Unicode and 8:15 that's listed as correct. 8:18 And here we only letters and punctuation and 8:21 then we have one that's not filled in at all. 8:24 So we can add another one here, and let's just say ASCII only. 8:26 We'll hit Save, and now we see that ASCII only shows up, and it's not that. 8:33 One other thing I want to show real quick is that we can control the number 8:40 of answers that pop up. 8:46 If we were to come over here to our forms and come to here, we can say extra= and 8:49 then give it a number. 8:53 And if we refresh, we had three and so now there's two extra, four and five. 8:55 You can also combine this with min, I think it's min_count and 9:01 max_count, which will let you control the minimum and maximum number of forms. 9:07 That's a good start, but we can go a little bit further. 9:14 Check out the formset docs in the teachers notes, and then come back for 9:17 the next video, where we'll talk about inline formsets. 9:20
You need to sign up for Treehouse in order to download course files.Sign up