2025-01-11 | Pretty Printed | Intro to Django Crispy Forms: Easy Form Styling
Django Crispy Forms无需手写HTML轻松打造美观表单
标签
媒体详情
- 上传日期
- 2025-06-27 09:54
- 来源
- https://www.youtube.com/watch?v=X8ECf3Ow3ww
- 处理状态
- 已完成
- 转录状态
- 已完成
- Latest LLM Model
- gemini-2.5-pro
转录
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.
最新摘要 (详细摘要)
概览/核心摘要
本视频详细介绍了如何运用 Django Crispy Forms 库,在不直接编写 HTML 的前提下,高效地为 Django 表单添加样式和控制布局。其核心是将表单的视觉呈现逻辑从模板(HTML)迁移至 Python 代码(forms.py),通过 FormHelper 和 Layout 对象以编程方式定义表单结构与外观。
视频演示了完整的集成流程:首先安装 django-crispy-forms 主库和特定的模板包(以 crispy-bulma 为例),然后在 Django 项目的 settings.py 中进行配置。在模板中,仅需使用 {% crispy form %} 标签,即可将一个无样式的标准 Django 表单渲染为遵循特定 CSS 框架(如 Bulma)规范的、结构清晰、样式美观的表单。
关键功能包括:
* Form Helper (FormHelper):一个核心类,用于配置表单的全局属性(如 id, class, method)和整体布局模式,例如一键切换为标签在左、输入框在右的水平布局。
* 布局 (Layout):允许在 Python 代码中精确定义表单字段的显示顺序、通过 Field 对象添加属性(如 placeholder),并使用 InlineRadios 等特定组件控制字段的渲染方式。
* 便捷的组件添加:可轻松在布局中加入功能性元素,如带有特定 CSS 类的提交按钮。
* 无缝的验证集成:Crispy Forms 能自动捕获 Django 的表单验证错误,并根据所选模板包的视觉约定(如将字段边框变红并在下方显示错误信息),将其友好地展示给用户,无需编写任何额外的错误处理模板逻辑。
视频指出,Crispy Forms 对标准或简单表单极为高效,能显著简化模板代码。然而,对于具有高度定制化需求的复杂表单,其灵活性可能受限于库自身提供的组件和功能。在这种情况下,开发者需权衡其便利性与自定义的难度,并可能考虑 Django Widget Tweaks 这类提供更细粒度控制但代码更冗长的替代方案。
Django Crispy Forms 简介
本视频旨在介绍 Django Crispy Forms 库,展示如何利用它创建样式化的表单,而无需手动编写 HTML。其核心思想是:
* 在 forms.py 中集中定义表单的逻辑与外观。
* 在模板中,通过一个简单的模板标签将表单对象传递给库,由库依据配置自动生成符合特定 CSS 框架(如 Bulma)规范的 HTML 结构和样式。
* 目标是实现与手动编写的 HTML 具有相同视觉效果的表单,同时大幅简化开发流程。
安装与配置
使用 Django Crispy Forms 需要安装主库和至少一个模板包。视频以 Bulma CSS 框架为例进行演示:
- 安装主库与模板包:
- 通过
pip分别安装:
bash pip install django-crispy-forms pip install crispy-bulma
- 通过
- 配置
settings.py:- 将
crispy_forms和crispy_bulma依次添加到INSTALLED_APPS列表中。
python INSTALLED_APPS = [ # ... 'crispy_forms', 'crispy_bulma', # ... ]
- 将
- 指定模板包:
- 在
settings.py中设置CRISPY_ALLOWED_TEMPLATE_PACKS,定义允许使用的模板包。
python CRISPY_ALLOWED_TEMPLATE_PACKS = ['bulma'] - 在
settings.py中设置CRISPY_TEMPLATE_PACK,指定当前项目默认使用的模板包。
python CRISPY_TEMPLATE_PACK = 'bulma' - 事实性内容:此配置意味着所有通过 Crispy Forms 渲染的表单都将自动生成符合 Bulma CSS 框架约定的 HTML,例如使用
div.field、div.control等特定结构。
- 在
模板中的使用
在 Django 模板中集成 Crispy Forms 的过程非常简洁,实现了视图逻辑与表现层的高度分离。
- 加载模板标签:
- 在模板文件顶部添加:
{% load crispy_forms_tags %}
- 在模板文件顶部添加:
- 渲染表单:
- 将传统的
{{ form.as_p }}或手动循环字段的方式,替换为单一标签:{% crispy form %} - 效果对比:视频演示了这一步带来的显著变化。原始的 Django 表单是无样式的垂直列表,而使用
{% crispy form %}后,表单立即呈现出由 Bulma CSS 定义的样式化外观,如输入框、标签和间距都变得美观。 - 重要原则:Crispy Forms 负责生成 HTML 结构并附加 CSS 类,但 CSS 文件本身必须由开发者在模板中单独引入(例如,通过 CDN 链接引入 Bulma 的 CSS)。
- 将传统的
Form Helper (FormHelper) 的应用
FormHelper 是 Crispy Forms 的控制中枢,用于在 forms.py 中配置表单的全局行为和 HTML 属性。
- 导入与实例化:
- 从
crispy_forms.helper导入FormHelper。 -
在表单类的
__init__方法中,实例化FormHelper并将其赋值给self.helper。
```python
from crispy_forms.helper import FormHelperclass ContactForm(forms.Form):
def init(self, args, kwargs):
super().init(args, kwargs)
self.helper = FormHelper()
`` 2. **控制表单 HTML 属性**: *self.helper.form_id = 'my-form':为生成的效果对比**:此设置会改变表单的整体结构,使字段标签(Label)从默认的输入框上方,移动到输入框的左侧,形成对齐的视觉效果,这在 Bulma 框架中是通过特定的 class 实现的。
- 从
布局 (Layout) 的定制
Layout 对象提供了对表单字段级别进行精细控制的能力,包括顺序、渲染方式和附加属性。
- 导入
Layout及相关组件:- 从所选模板包的
layout模块导入所需组件(如Layout,Field,Submit)。视频强调应从模板包(如crispy_bulma.layout)导入,以确保最佳兼容性。
- 从所选模板包的
- 定义字段顺序与布局:
-
通过
self.helper.layout = Layout(...)来定义表单的结构。字段将按照Layout对象中列出的顺序进行渲染。
```python
from crispy_bulma.layout import Layout, Field
from crispy_forms.layout import Submitself.helper.layout = Layout(
Field('name', placeholder='Your Name'),
Field('email', placeholder='Your Email'),
# ... other fields
Submit('submit', 'Send Message', css_class='is-primary')
)
`` 3. **为字段添加属性**: * 使用Field对象包装字段名,可以方便地添加 HTML 属性,最常见的是为文本输入框添加placeholder。 4. **处理特殊字段类型**: * **内联单选按钮 (InlineRadios)**:导入并使用InlineRadios('field_name')可将默认垂直堆叠的单选按钮渲染为水平排列的内联样式。 * **调整文本区域大小**:通过Field('message', rows='4')可以直接控制textarea的默认显示行数。 5. **添加提交按钮 (Submit)**: * 在Layout中添加Submit对象,可以创建一个提交按钮。参数分别定义了按钮的name属性、显示的文本以及应用的 CSS 类(如is-primary` 在 Bulma 中代表主色调按钮)。
-
表单验证与错误显示
Crispy Forms 与 Django 的原生验证机制无缝集成,并能自动、优雅地展示验证错误。
- 视图中的处理逻辑:
- 在视图函数中,当收到 POST 请求时,需用请求数据实例化表单并调用
form.is_valid()。 - 如果验证失败,只需将这个包含错误信息的
form对象重新传递给模板即可。Crispy Forms 会自动检测到错误并进行渲染。
python def contact_view(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): # Process valid data and redirect return redirect('index') else: form = ContactForm() # If request is GET or form is invalid, render the form return render(request, 'index.html', {'form': form})
- 在视图函数中,当收到 POST 请求时,需用请求数据实例化表单并调用
- 自动化的错误显示:
- 效果对比:视频演示了当自定义验证器(如要求输入特定文本 "Python")失败时,Crispy Forms 的表现。它会自动为无效字段的输入框添加
is-danger类(使其边框变红),并在字段正下方以红色文本显示具体的错误消息。整个过程无需开发者编写任何if form.errors或if field.errors的模板逻辑。
- 效果对比:视频演示了当自定义验证器(如要求输入特定文本 "Python")失败时,Crispy Forms 的表现。它会自动为无效字段的输入框添加
核心结论
Django Crispy Forms 提供了一种强大而简洁的方式来管理 Django 表单的样式和布局。通过将表现层逻辑从模板转移到 Python 代码中,它使得模板文件极为干净,并能快速应用流行的 CSS 框架,同时自动处理验证错误的视觉反馈。该库是构建标准样式表单的绝佳选择,能显著提升开发效率。然而,对于需要高度定制化和复杂布局的表单,开发者应评估其提供的组件是否满足需求,权衡其便利性与潜在的灵活性限制。