speaker 1: Hey everyone, in today's video, I want to introduce you to the Jango cririy forms library and show you how you can use that library to create a form like this. So this form was defined in my form, stop pi, the way that it looks and the way that it works. And inside the template, I didn't have to like build out this form myself. So this is a way to create forms and have them look the way that you wanna look in Jango without having to write any html. You basically just PaaS the form to the template, you using a template tag, and it will generate the layout that you want using this library. So that's what I want to introduce you in this video. Before I get started, I just wanna say, if you need help with anything jangle related, feel free to reach out to me. I help people one on one over zoom. So just go to my pretty printed com slash coaching page or click the link in the description below and you can learn more about how you can work with me directly. If you have trouble with anything, your app. So with that set, let's get started on this. Jango crispy forexample. So let me start by showing you what I want to build. So this is the final look of the form that I want to create. So this is styled with bma. Now I'll show you how to use crispy forms to get this final output. So this is what it looks like. This has no Jango stuff in it. This is just pure html. So let me show you in this index, html. This is just the html for this, with all the fields and css classes and everything here to generate this look for the form. So I want to replicate that with jgo crispy forms. So I also have a contact form set up that has all the same fields as this form here, except I haven't implemented this yet. So I just wanted to show you this. So we have a reference. So let me duplicate this tab and I'm going to work here and then I'll go back to the other tab to compare the result. So first I'm gonna na get this form set up. So let me go over to my templates and I'll duplicate this and I'll name this one bma. So this will be the original boma. And then the index here. I'll remove everything inside. So let me remove everything inside the body. Well actually not everything. I to remove everything except for the container inside of the body. Okay, so that's what I have here. And now I want to inject the form into this. So I'll go over to views pi and I'll import the form. So from forms, import contact form. And then what I want to do is I want to create it. So contact form, it's going to take in nothing because this is a git request, and I'll just PaaS it to the template. And then if I just go back to the template so index html, I can put the form here. So form, and then I can do like as underscore peright. So if I refresh this now, this is what it looks like. So obviously, this is a long way from this. This is the in result that I want. And if you're familiar with working with jgo forms, like you have to find a way to add like the css to that. So that's where jgo crispy forms comes in. It will allow me to get the end result that I want without having to modify any of the html. And I'll show you how that works. So first let me start by installing jingle crispy forms. So in my terminal, I'll do pip install jgo dash crispy dash forms. Then once it's installed, I can go over to settings, out pi and I can add it to the installed apps crispy forms. And then once you have crispy forms, you have to decide on a template pack. So the template pack will basically make your form look like some css framework. So there's bootstrap, there's foundation, they have one for tailwind, but I'm going to use boma, right? That's the css framework that I like. So I'm going to use boma and it's just like an approach to styling html, right? So I need to install it. So it's going to be pipped. Install crispy bma and it really doesn't matter which one you choose because all the template packs work in a similar way. They may have different features depending on what the css framework provides, but the idea is the same in all of them. So if you wanna use like bootstrafor example, you can use that one. You can install the crispy bootstrap 51. So here you just add crispy bma to install apps. Next, I need to tell it which template packs are available. So under installed apps, I can put this at the bottom. But since I'm already here, I can create a setting called crispy allowed d template packs. And this will just be a list or two pull of things. So in my case, I only have one edbulmont. But if you wanna support multiple template packs, you can. So if you wanna have like themes in your app, you can where the user can switch themes. But for this video, I'm just gonna to use one template pack bulma. And then once you have the list of allow template packs, you have to specify the template pack that you want to use. You can only use one at a time, obviously. So crispy template pack. And I want that to be bma. So what this means is my form will be constructed in the way that bma expects. So if you go to this boma, I html notice that I have a div that has like a field in it. And inside the the field, I have like a field label in a field body is horizontal. These are all bma conventions. So when I use crispy form, it will automatically follow those conventions. So to get our form to work, let's go over to index I html. First thing I need to do is I need to load the template tag so I can do load a crispy forms tag. Those are the template tags that you want to load. And then once you have that, you can do this. So I can change this form as p to crispy, and then my form object. So I'll remove as p. And let's just take a look at what this looks like. And before I show you, just noyou have to have the css available. So the css is independent of crispy form. Crispy form will build the structure and add all the css classes onto the html. But I still need to bring in the css. So I have the link to the cdn for the boma css. So let me go ahead and start the server again and make sure there are no errors. Yeah, no errors. So I'll go back here and I'll refresh. And we see it already starts to look like the form over here. So it's not exactly the same, but it's pretty close, right? We see the the labels, we see the inputs have the right styling on them and it's roughly the right size. But we want to modify this further. So it looks exactly like this over here. So let me go back to the code. And the first thing I want to do is I want to remove this asterisk, right? So these asterisks appear for the fields that are required, in this case, all the filter required. So to get rid of that, I need to define some custom css. And it's just asterisks risk. And then I'll just do display none. I believe it's asterisks, plural. I think it's actually singular. So asterisk, singular refresh. And now we see the asterisk goes away. So that's a simple thing. That's just, they give you those asterisk because you want na change how that appears for required fields. But because all my fields are required, I just wanna remove it completely. So now let's get into the actual crispy form part. So here I call crispy form on here, and I won't have to make any other changes to the html. Everything else that I'm going to modify is going to happen in form stop oppiso. The first thing I'm going to do is I want to create something called a form helper. So to do that, I need to import this form helper from crispy forms. So I'll do from crispy underscore forms helper, import form helper, capital f, capital H, and then I can put this form helper on the form. So this form helper will allow me to define some attributes that control how the form works. So like where the form goes, like the action of it, the type. So get our post and I can even put like a class on it or an ID. So what I'll do here is in the dunder knit for my form. So I'll create it. So dunder knit here and I'll PaaS in arcs and keyword arcs in case this is used in a different way just to cover all cases. What I'll do is I'll initialize the existing form by calling super so super annits and passing the arcs and keyword arcs. I won't be using them, but just to follow the convention, I'm passing those in. And then what I want to do is I want to instantiate the form helper. So I'm gonna to put it on the form itself. So I'll do self helper equals form helper, and this is just a place to keep it. You could define the form helper outside of the form, but I think defining the instance of the form helper on the form is the best place to put it. So now that I have the form helper, I can define some things on it. So if I want to put an ID for the form, I can say my form and that's gonna to create an ID and then I can even define a class for the form, let's say form class. And I know that I wanna put some space between the top of the page and the form. So we see how here it's all the way to the top. Whereas in this one, there's a little bit of space. That's because there's a margin top at the form level. So I'll just put mt H5. So that will add a margin top dash five class to the form. So now when I refresh this, we see it goes down a little bit because the html has been modified. So let's take a look here. We See Class, we see mt five, we see the ID is my form, and we see the method is post. So it created a form for me and it just added those three things in there because I defined them on the form helper. So I don't have to create a form element myself in html. Instead, I define these things on the form helper and it adds it there for me. So these are pretty basic, but the most important part that I want to show you is something called the layout. So the helper has something called layout on it. And what I can do is I can define what the form is going to look like. So what I'll do is I'll import some stuff. So we'll start with one thing and I'll import more as I use it. So I'll do from crispy bma layout import layout. And just know that crispy forms itself has a layout. But typically when you use a template pack, you want na import everything from the template pack in case it makes any changes to these. So this is probably the same as the one in crispy forms. So it's just importing from crispy forms and putting it in crispy bma and you're importing that one. But if it happens to make any changes, you would want to import the one from the template pack that you're using. So I'm importing it from crispybma layout, not crispyforms layout. So I have layout here. And what I can do is I can go down to the helper and I can do layouts. And in here I can list all the fields that I'm interested in. So let's start with one so name. So I'll just do that one and let me refresh and show you what happens. You see now name is the only thing that appears because the layout that I'm defining for this form only has one field. So if I wanted to add the other fields, I can add them. So let me add just two. So email and then phone number are the next two. So I'll add those s. And if I refresh, we see those to get added. But of course, I want all of them. So I'll just go ahead and add those. So department follows that preferred contact subject and then message and notice that they appear visually in the order that I specify. So if I put like the message at the top, for example, and put a comma there, and then refresh this, we see the message appears at the top. So the layout is controlling the literal look of the form. But I want the the message to be at the bottom, just like the original example. So I'll put it back here and I'll save it, right? So Yeah, this is the right order. So we see it's starting to look like my original form over here. But one big difference is you notice that the labels are all on the left over here, whereas in this one, the labels appear on top of each field. So in boma, the way to get the labels to appear to the left of each field is called making the form horizontal. So what I can do is on the helper. I can do self helper form underscore horizontal equals. So just by sending this to it will change this to a horizontal form. And now we see that name, email and so on all appear on the left hand side. So now let's make some more modifications. So we see that each input that's a text has a placholder. So how do we get the placeholder to appear? Well, what we need to do is we need to go up and we need to import field from layout, and then we need to change this to a field. So first let me change name to a field without adding anything to a field, and we'll see that we get the exact same thing. So if I refresh is exactly the same, but what I can do is I can add a placeholder onto this field now because I wrapped name in a field. So if I do placeholder equals name and I refresh, we see the name placeholder appears. So I can do the same thing for the other ones. So I'll put a field here. Field here. Let's see. Email, phone, subject and message. These are the ones that I wanna put a place order on. So let's just add that onto these fields. And then the mesi want, I believe, is write something for the message. What's your message about for the subject? For the phone, let's just put phone number. For email, let's just put email. Okay, so let's go over refresh. And now we see the placeholders appear over here. It looks like the placeholders are about the same, right? So now the next thing that I noticed that is a little different is the radio button. So we see here they're stacked on top of each other whereas here they're like inline. So there's actually a field for that. It's called inline radios. So I can import that from cririspy boma layout. So inline radios. And then I'll copy that and I'll put it on preferred contact. And now by simply wrapping that, that's one extra print. By wrapping that, we see, we get an import error. And it's actually because I don't know why they did this, but they put it in a different location. So crispy boma boma, import this inline radio. So let's just move it down here and now. Okay, it runs and refresh. And now we see it's inline. So we see email and phone are inline properly. Also, I noticed that on the original there's not a default one, but that's fine. The drop down is fine. And the last thing I notice is the send message button is missing. So what I can do is I can define a submit button. So from here I can import submit, go down here and add submit to the layout. We'll call this submit. It's a submit button. And then send message is the text. And then I need to add a css class to it. So css class in boma, it is primary to get that color. So if I refresh here now, we see sin message appears there. And also I notice that the text box is a lot smaller. So let me go ahead and modify the message. I can just add rows and columns. So rows will be four and columns will be 20 and refresh this. And now we see it's about the same size, right? Slightly slightly off, but it's about the same size and the labels are slightly different. Let's see. Yeah preferred contact has a question mark in the original, but no question mark here. I can add a label if I went into, but I don't think it's that big of a deal. But as you can see, we got the the layout of the original form by just modifying things inside of form stop pi. So notice that when I go back to index, this is the only thing that I have for the form. So there's no html, no css defined here. It's all happening in the form stop pi. As opposed to when you're using something like jingo widget tweaks, you define the extra fields like when you're rendering the field. So you're still responsible for building the form here in the html and that you can add on any extra things on the form that you like. But here in crispy forms, you basically just say, here's my crispy form. And then you see the layout is defined here in form. Saw pii inside of the layout that's defined on the helper. So that's to get the form to look in the way that we want. Now what about behavior? So the typical behavior is validation. So of course, it's gonna to add typical validation. So like if I hit the submit, it's gonna tell me like I need to fill out these fields, but I wanna make it fail just for like a random field. So what I'll do is I'll define a validator. And I'll call this validate field. It's just going to be a function. It's going to take a value. And I'll say if value does not equal Python, for example, I'm gonna to raise form stop validation error, you must enter Python. So I'll come back to this in a moment and show you how this works. But first I need to go to view stop pi and I need to make the form work in the post case. So I'll say if request method is post, I'm going to instantiate the contact form using the data from the post request and I'm going to run form is valid. So I'm not going to do anything if the form is valid, I'm just going to redirect back to the same form. So home, I need to import redirect. The point is I wanna call is valid. So the form gets validated and I'll put an else here so the form doesn't get overwritten and the invalid four will be passed to the template so you can see the errors. So first let me fill out the form with no extra validation. So I'll say Anthony anthat preprinted com. I'll type in random numbers for the phone number. I need help. Please help me. And if I send message, we see this error. So the form is submitted properly. It just didn't work for the redirect. I think inside of my url's I don't have like a name. Oh, the name is index, not home. So that's a that's a minor issue. Let me just change that to index. And if I go back and then send mesagain, now I work. So it's redirecting back to the original four. So now let me add that validation in there so I can go to form stop pi. And let's say on the name field, I'm gonna add that validator that I just created it. So I'll say validators equals is gonna to be a list, and then I'm passing in the validate field function that I just defined. So now when I try to submit the form, if I don't put Python there, it's going to fail. And let's see what it looks like when it fails. So I'll put my name again, which is not Python, and I'll put some random numbers, random numbers without letters. And now I'll submit and we see I get the air right. So in boma, the convention is you can turn the field red and then it has the error message text directly underneath the field. So I didn't have to define the places where the error stuff would go. I didn't have to define the change in the css class for the input. It all works automatically because I'm using crispy forms and crispy bma to generate this whole form. So that's the main example that I want to show in this video, is pretty simple. And I think this works pretty well for simple forms. As your forms get more complicated and there's more styles to them, you're kind of dependent on what the libraries can supply for you. So meaning what crispy bma can do for you and what crispy forms can do for you. Because if the libraries don't supply like the appropriate feels that generate the htmin the right way, then you have to like customize yourself in the more customization you do that more, you have to wonder like, was it worth using the library? So that's a decision that you have to make. Me personally, I think Jango widget tweaks is a little bit better. It gives you more control, even though it's more verbose. But I do think this is okay for simple forms. So what do you guys think? Like do you like this approach of building forms in Jango or would you prefer a different approach? Just just let me know in the comments down below. So that's it for this video. That's all I want to show you. If have any questions about anything that I've done here, feel free to leave a comment down below. If you like this video, please give me a thumbs up. And if you haven't subscribed to my channel already, please subscribe. So thank you for watching, and I will talk to you next time.