跳轉到

Bootstrap 表單樣式

開始之前

任務目標

在這個章節中,我們會完成:

  • 了解為什麼需要美化表單
  • 認識 django-bootstrap5 套件
  • 使用 bootstrap_form 快速渲染表單
  • 使用 bootstrap_field 客製化個別欄位
  • 處理表單錯誤訊息的顯示
  • 掌握 Bootstrap 表單的最佳實踐

為什麼需要美化表單?

在上一章節中,我們使用 {{ form.as_p }} 自動生成表單,雖然功能正常,但樣式非常陽春。

原生表單的問題

使用 Django 原生的表單渲染:

{{ form.as_p }}

會產生類似這樣的 HTML:

<p>
  <label for="id_title">標題:</label>
  <input type="text" name="title" maxlength="200" required id="id_title">
</p>
<p>
  <label for="id_content">內容:</label>
  <textarea name="content" cols="40" rows="10" required id="id_content"></textarea>
</p>

原生表單的缺點

  • ❌ 沒有 CSS 類別,無法套用樣式
  • ❌ 錯誤訊息格式不統一
  • ❌ 欄位排列不美觀
  • ❌ 在手機上使用體驗不佳
  • ❌ 與網站整體風格不一致

Bootstrap 表單的優勢

使用 Bootstrap 樣式的表單:

Bootstrap 表單的好處

  • ✅ 自動套用 Bootstrap 樣式類別
  • ✅ 統一的錯誤訊息顯示
  • ✅ 響應式設計,支援各種螢幕尺寸
  • ✅ 美觀且專業的外觀
  • ✅ 與網站整體設計一致

使用 django-bootstrap5

django-bootstrap5 是一個第三方套件,可以讓我們輕鬆地在 Django template 中使用 Bootstrap 5 樣式。

套件已安裝

在先前的章節中,我們已經安裝並設定了 django-bootstrap5:

  • ✅ 已安裝套件
  • ✅ 已加入 INSTALLED_APPS
  • ✅ 已在 base.html 中載入 CSS 和 JavaScript

確認安裝

如果忘記是否已安裝,可以檢查:

  1. settings.pyINSTALLED_APPS 中有 "django_bootstrap5"
  2. base.html:有 {% load django_bootstrap5 %}{% bootstrap_css %}{% bootstrap_javascript %}

主要功能

django-bootstrap5 提供的 template tags:

Template Tag 用途
{% bootstrap_form %} 渲染整個表單
{% bootstrap_field %} 渲染單一欄位
{% bootstrap_button %} 渲染按鈕

使用 bootstrap_form 美化表單

讓我們使用 bootstrap_form 來美化文章建立表單。

修改 Template

修改 blog/templates/blog/article_create.html

blog/templates/blog/article_create.html
{% extends "blog/base.html" %}

{% load django_bootstrap5 %}

{% block title %}
  建立文章 - Django 大冒險
{% endblock title %}

{% block blog_content %}
  <div class="card">
    <div class="card-body">
      <h2 class="card-title mb-4">
        建立文章
      </h2>

      <form method="post">
        {% csrf_token %}

        {% bootstrap_form form %}

        <div class="d-flex gap-2 mt-3">
          {% bootstrap_button button_type="submit" content="建立文章" %}
          {% bootstrap_button button_type="reset" content="清除內容" button_class="btn-info" %}

          {% url 'blog:article_list' as cancel_url %}  {# (1)! #}
          {% bootstrap_button button_type="link" href=cancel_url content="取消" button_class="btn-secondary" %}
        </div>
      </form>
    </div>
  </div>
{% endblock blog_content %}
  1. 文章列表的 url 放入變數 cancel_url,而不是直接印出

只需兩步!

  1. 載入 template tag{% load django_bootstrap5 %}
  2. 使用 bootstrap_form{% bootstrap_form form %}

原本複雜的表單 HTML 現在只要一行!

另外按鈕也可以透過 {% bootstrap_button %} 變得簡單

測試結果

訪問 http://127.0.0.1:8000/blog/articles/create/

你會看到:

  • ✅ 欄位自動套用 form-control 類別
  • ✅ Label 使用 form-label 類別
  • ✅ 欄位有適當的間距(mb-3
  • ✅ 錯誤訊息顯示在欄位下方
  • ✅ 必填欄位有標示

bootstrap_form 做了什麼?

{% bootstrap_form form %} 會:

  1. 遍歷表單的所有欄位
  2. 為每個欄位加上 Bootstrap 類別
  3. 渲染 label、input、help text
  4. 處理錯誤訊息的顯示
  5. 加入適當的 HTML 結構

相當於自動執行了我們在前一章節手動做的事!

客製化表單顯示

設定 bootstrap_form 參數

bootstrap_form 支援多種參數來客製化顯示:

blog/templates/blog/article_create.html
{% extends "blog/base.html" %}

{% load django_bootstrap5 %}

{% block title %}
  建立文章 - Django 大冒險
{% endblock title %}

{% block blog_content %}
  <div class="card">
    <div class="card-body">
      <h2 class="card-title mb-4">
        建立文章
      </h2>

      <form method="post">
        {% csrf_token %}

        {% bootstrap_form form layout='horizontal' %}

        <div class="d-flex gap-2 mt-3">
          {% bootstrap_button button_type="submit" content="建立文章" %}
          {% bootstrap_button button_type="reset" content="清除內容" button_class="btn-info" %}

          {% url 'blog:article_list' as cancel_url %}
          {% bootstrap_button button_type="link" href=cancel_url content="取消" button_class="btn-secondary" %}
        </div>
      </form>
    </div>
  </div>
{% endblock blog_content %}

常用參數

  • layout'vertical'(預設)、'horizontal''inline'
  • size'sm''lg'(欄位大小)
  • show_labelTrue(預設)、False(是否顯示 label)
  • show_helpTrue(預設)、False(是否顯示說明文字)
  • error_css_class:自訂錯誤的 CSS 類別
  • required_css_class:必填欄位的 CSS 類別

水平排列表單

水平排列可以讓 label 和 input 在同一行:

{% bootstrap_form form layout='horizontal' %}

效果:

標題   [___________________]
內容   [___________________]
作者   [___________________]

設定欄位大小

讓欄位更大:

{% bootstrap_form form size='lg' %}

或更小:

{% bootstrap_form form size='sm' %}

使用 bootstrap_field 精細控制

如果需要對個別欄位有更多控制,可以使用 bootstrap_field

個別渲染欄位

修改 blog/templates/blog/article_create.html

blog/templates/blog/article_create.html
{% extends "blog/base.html" %}

{% load django_bootstrap5 %}

{% block title %}
  建立文章 - Django 大冒險
{% endblock title %}

{% block blog_content %}
  <div class="card">
    <div class="card-body">
      <h2 class="card-title mb-4">
        建立文章
      </h2>

      <form method="post">
        {% csrf_token %}

        {% bootstrap_field form.title show_label=True placeholder="請輸入文章標題..." %}

        {% bootstrap_field form.content rows=15 %}

        {% bootstrap_field form.author show_label=False %}

        <div class="d-flex gap-2 mt-3">
          {% bootstrap_button button_type="submit" content="建立文章" %}
          {% bootstrap_button button_type="reset" content="清除內容" button_class="btn-info" %}

          {% url 'blog:article_list' as cancel_url %}
          {% bootstrap_button button_type="link" href=cancel_url content="取消" button_class="btn-secondary" %}
        </div>
      </form>
    </div>
  </div>
{% endblock blog_content %}

bootstrap_field 的優勢

使用 bootstrap_field 可以:

  • 個別設定參數:每個欄位可以有不同的設定
  • 加入 placeholder:提示使用者輸入內容
  • 控制 rows:調整 textarea 的高度
  • 顯示/隱藏 label:根據需求調整
  • 加入自訂類別:透過 addon_beforeaddon_after 等參數

bootstrap_field 常用參數

參數 說明 範例
show_label 是否顯示 label show_label=False
placeholder 輸入提示文字 placeholder="請輸入..."
help_text 說明文字 help_text="標題最多 200 字元"
size 欄位大小 size='lg'size='sm'
rows textarea 行數 rows=10
addon_before 前綴文字或圖示 addon_before='<i class="bi bi-person"></i>'
addon_after 後綴文字或圖示 addon_after='字元'

加入圖示和附加元素

為欄位加入圖示:

blog/templates/blog/article_create.html
{% extends "blog/base.html" %}

{% load django_bootstrap5 %}

{% block title %}
  建立文章 - Django 大冒險
{% endblock title %}

{% block blog_content %}
  <div class="card">
    <div class="card-body">
      <h2 class="card-title mb-4">
        建立文章
      </h2>

      <form method="post">
        {% csrf_token %}

        {% bootstrap_field form.title addon_before='<i class="bi bi-pencil"></i>' placeholder="請輸入標題..." %}

        {% bootstrap_field form.content addon_before='<i class="bi bi-file-text"></i>' rows=10 %}

        {% bootstrap_field form.author addon_before='<i class="bi bi-person"></i>' %}

        <div class="d-flex gap-2 mt-3">
          {% bootstrap_button button_type="submit" content="建立文章" %}
          {% bootstrap_button button_type="reset" content="清除內容" button_class="btn-info" %}

          {% url 'blog:article_list' as cancel_url %}
          {% bootstrap_button button_type="link" href=cancel_url content="取消" button_class="btn-secondary" %}
        </div>
      </form>
    </div>
  </div>
{% endblock blog_content %}

效果會在輸入框前面顯示圖示。

處理錯誤訊息

django-bootstrap5 會自動處理錯誤訊息的顯示。

錯誤訊息樣式

當表單驗證失敗時:

  • ✅ 欄位會自動加上 is-invalid 類別(紅色邊框)
  • ✅ 錯誤訊息顯示在欄位下方
  • ✅ 使用 .invalid-feedback 樣式(紅色文字)

測試錯誤訊息

  1. 訪問建立文章頁面
  2. 不填寫任何內容,直接提交
  3. 觀察錯誤訊息的顯示

你會看到:

標題
[________________] ← 紅色邊框
✗ 標題不能空白      ← 紅色錯誤訊息

全域錯誤訊息

如果使用 {% bootstrap_form form %} 選染表單那全域的錯誤訊息表單會自己處理, 但如果使用 {% bootstrap_field %} 單獨渲染每個欄位則需要自己渲染全域錯誤來渲染:

blog/templates/blog/article_create.html
{% extends "blog/base.html" %}

{% load django_bootstrap5 %}

{% block title %}
  建立文章 - Django 大冒險
{% endblock title %}

{% block blog_content %}
  <div class="card">
    <div class="card-body">
      <h2 class="card-title mb-4">
        建立文章
      </h2>

      {% bootstrap_form_errors form type='non_fields' %}

      <form method="post">
        {% csrf_token %}

        {% bootstrap_field form.title addon_before='<i class="bi bi-pencil"></i>' placeholder="請輸入標題..." %}

        {% bootstrap_field form.content addon_before='<i class="bi bi-file-text"></i>' rows=10 %}

        {% bootstrap_field form.author addon_before='<i class="bi bi-person"></i>' %}

        <div class="d-flex gap-2 mt-3">
          {% bootstrap_button button_type="submit" content="建立文章" %}
          {% bootstrap_button button_type="reset" content="清除內容" button_class="btn-info" %}

          {% url 'blog:article_list' as cancel_url %}
          {% bootstrap_button button_type="link" href=cancel_url content="取消" button_class="btn-secondary" %}
        </div>
      </form>
    </div>
  </div>
{% endblock blog_content %}

常見問題

bootstrap_form 和 form.as_p 有什麼差別?

特性 form.as_p bootstrap_form
樣式 無樣式 Bootstrap 樣式
CSS 類別 自動加入
錯誤訊息 基本顯示 Bootstrap 樣式
客製化 困難 支援參數
響應式

如何自訂錯誤訊息樣式?

django-bootstrap5 會自動套用 Bootstrap 的錯誤樣式(is-invalidinvalid-feedback)。

如果需要更多客製化,可以使用 CSS:

.invalid-feedback {
    font-size: 0.9rem;
    font-weight: bold;
}

.is-invalid {
    border-color: #dc3545;
    border-width: 2px;
}

任務結束

完成!

恭喜你完成了這個章節!現在你已經:

  • 了解為什麼需要美化表單
  • 認識 django-bootstrap5 套件
  • 使用 bootstrap_form 快速渲染表單
  • 使用 bootstrap_field 客製化個別欄位
  • 處理表單錯誤訊息的顯示
  • 掌握 Bootstrap 表單的最佳實踐

Bootstrap 表單的關鍵要點

  1. 優先使用 bootstrap_form:大多數情況下已經足夠
  2. 需要客製化時使用 bootstrap_field:可以精細控制每個欄位
  3. 善用參數:placeholder、rows、addon_before 等
  4. 統一樣式:建立可重用的 form template
  5. 錯誤訊息:django-bootstrap5 會自動處理

從原本需要手寫大量 HTML 和 CSS 類別,到現在只需要一行 {% bootstrap_form form %},這就是 django-bootstrap5 的威力!

記住:

  • ✅ 使用 {% load django_bootstrap5 %} 載入 template tags
  • ✅ 使用 {% bootstrap_form form %} 渲染整個表單
  • ✅ 使用 {% bootstrap_field form.field_name %} 渲染個別欄位
  • ✅ 善用參數客製化顯示

現在你的 Django 表單不僅功能完整,而且美觀專業!