使用django-crispy-forms美化表單UI
前言
歐克,繼續來寫這個中臺項目衍生出來的系列文章
今天介紹一個可以美化界面的庫
Django 開發講究個快,天下武功,唯快不破
forms 功能自然是要用的,自帶表單 UI 生成和驗證,實現 demo 時非常方便
之前我在 DjangoStarter 框架里已經封裝了一套 forms 行為和樣式了,在 src/django_starter/contrib/forms 里
這套已經不錯了,也是用 TailwindCSS 來實現樣式,挺好看的
不過在開發中臺項目的時候,我發現了 django-crispy-forms 這個庫,提供了更多美化表單 UI 的靈活性。
DjangoStarter里的實現
先來看看 DjangoStarter 框架的實現
forms
├─ widgets
│ ├─ __init__.py
│ ├─ multiple_file.py
│ └─ flowbite_date_picker.py
├─ templates
│ └─ django_starter
│ └─ forms
│ ├─ widgets
│ └─ form_template.html
├─ __init__.py
├─ widget_classes.py
├─ mixins.py
└─ base.py
template
src/django_starter/contrib/forms/templates/django_starter/forms/form_template.html
{% for field in form %}
<div>
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
<div class="mt-2 text-sm text-gray-500 dark:text-gray-200">
{{ field.help_text }}
</div>
<div class="mt-2 text-sm text-red-600 dark:text-red-500">
{{ field.errors }}
</div>
</div>
{% endfor %}
widgets
src/django_starter/contrib/forms/widgets/flowbite_date_picker.py
from django import forms
class FlowbiteDatePickerWidget(forms.DateInput):
template_name = 'django_starter/forms/widgets/flowbite_date_picker.html'
def __init__(self, attrs=None, custom_class=''):
final_attrs = {'class': custom_class}
if attrs:
final_attrs.update(attrs)
super(FlowbiteDatePickerWidget, self).__init__(attrs=final_attrs)
src/django_starter/contrib/forms/widgets/multiple_file.py
from django import forms
class MultipleFileInput(forms.ClearableFileInput):
allow_multiple_selected = True
class MultipleFileField(forms.FileField):
def __init__(self, *args, **kwargs):
kwargs.setdefault("widget", MultipleFileInput())
super().__init__(*args, **kwargs)
def clean(self, data, initial=None):
single_file_clean = super().clean
if isinstance(data, (list, tuple)):
result = [single_file_clean(d, initial) for d in data]
else:
result = [single_file_clean(data, initial)]
return result
forms 代碼
src/django_starter/contrib/forms/mixins.py
from django import forms
from .widget_classes import *
class BaseFormMixin:
"""提供表單樣式的通用混入類"""
widget_classes = {
forms.TextInput: TEXT_INPUT_CLASS,
forms.Textarea: TEXT_AREA_CLASS,
forms.EmailInput: TEXT_INPUT_CLASS,
forms.PasswordInput: PASSWORD_INPUT_CLASS,
forms.Select: SELECT_CLASS,
forms.DateInput: DATE_INPUT_CLASS,
forms.NumberInput: NUMBER_INPUT_CLASS,
}
def apply_widget_classes(self):
"""根據widget類型為表單字段應用樣式"""
for field_name, field in self.fields.items():
widget_class = self.widget_classes.get(type(field.widget))
if widget_class:
field.widget.attrs.update({'class': widget_class})
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.apply_widget_classes()
widget_classes.py 的代碼就不貼了
就是 Tailwind CSS 的樣式
crispy-forms 是咋實現的
安裝后,簡單配置下就能用了
使用起來類似下面這樣
{% load crispy_forms_tags %}
<div class="sm:col-span-6">
{{ form.name|as_crispy_field }}
</div>
<div class="sm:col-span-3">
{{ form.dvr_brand|as_crispy_field }}
</div>
<div class="sm:col-span-3">
{{ form.dvr_model|as_crispy_field }}
</div>
<div class="sm:col-span-3">
{{ form.dvr_ip|as_crispy_field }}
</div>
<div class="sm:col-span-3">
{{ form.status|as_crispy_field }}
</div>
安裝
安裝依賴
pdm install django-crispy-forms
然后添加到
INSTALLED_APPS = (
...
'crispy_forms',
)
Template packs
然后還得安裝 Template packs
不然只是個空殼
官方支持的只有 Bootstrap 系列,有點 out 了
好在社區也提供了不少,這里我只關注 Tailwind CSS 的庫,名字是 crispy-tailwind
pdm add crispy-tailwind
其他 UI 庫還有很多,感興趣的同學可以在官網看到: https://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
這個同樣也得添加進去
INSTALLED_APPS = (
...
'crispy_forms',
'crispy_tailwind',
)
配置
在配置文件里修改默認的 Template Packs
src/config/settings/components/crispy_forms.py
CRISPY_ALLOWED_TEMPLATE_PACKS = "tailwind"
CRISPY_TEMPLATE_PACK = "tailwind"
使用
最簡單的用法是只修改模板文件
{% load crispy_forms_tags %}
<form method="post" class="my-class">
{{ my_formset|crispy }}
</form>
目前中臺項目也只用到了這個
搭配 django-select2 可以實現下拉搜索框
不過樣式不好改,我折騰了一段時間也沒改好,索性先不理了,反正就是一個快速實現的 DEMO
后續有需求再用 React 重寫頁面就行了
小結
我發現 Django 相關的技術還算是比較小眾的
一般寫這種文章就沒什么人看
我做 Django 也好幾年的時間了,框架源碼看了,腳手架也搞了,用得非常順手
雖然現在 python 的 web 框架有很多,不過所有項目最終都會成為 Django 的樣子??
就這樣吧,python 項目這一塊,我還是會繼續堅持 Django ,畢竟是真的方便好用
當然也不排斥嘗試新的玩意,比如最近有個 Litestar 號稱要干掉 FastAPI 的,感覺挺有意思的,有時間可以試試看

浙公網安備 33010602011771號