JavaRush /Курси /Модуль 3: Django /Робота з віджетами форм

Робота з віджетами форм

Модуль 3: Django
Рівень 12 , Лекція 7
Відкрита

У попередній лекції ми також зіткнулися з проблемою відображення помилок — адже не всі користувачі розуміють ображені коментарі Django про "неприпустимий формат". Ми навчилися їх красиво і зрозуміло виводити у шаблонах. Тепер — переходимо на новий рівень: віджети.

Що таке віджети в Django Forms?

Віджети (Widgets) — це міст між логікою форми та її HTML-представленням. Вони дозволяють відображати дані (або поля форми) у вигляді HTML-елементів, таких як <input>, <textarea>, <select> і так далі. По суті, вони визначають, як ваша форма виглядатиме у браузері.

Навіщо потрібні віджети? Уявіть, що ви відправляєте анкету для NASA, заповнюючи поле типу "вага в кілограмах" у вигляді випадаючого списку від 1 до 10 000. Без віджета таке поле виглядало б як звичайний <input>, і хтось міг би ввести там текст "багато". Віджети дозволяють перетворити такі поля на інтерактивні елементи з валідацією вводу.

Стандартні віджети в Django

Django надає широкий вибір вбудованих віджетів для різних типів полів форми:

Віджет HTML-елемент Підходить для
TextInput <input type="text"> Текстові рядки (ім'я, логін тощо)
Textarea <textarea> Багаторядкові текстові поля (коментарі, описи)
NumberInput <input type="number"> Числові поля
EmailInput <input type="email"> Адреси електронної пошти
PasswordInput <input type="password"> Паролі
Select <select> Випадаючі списки
CheckboxInput <input type="checkbox"> Прапорці (галочки)
DateInput <input type="date"> Поле для введення дати

Приклад: коли ви створюєте поле типу forms.CharField(), Django автоматично використовує віджет TextInput.

from django import forms

class SimpleForm(forms.Form):
    name = forms.CharField(max_length=50)  # Цей CharField автоматично використовує TextInput.

Зміна віджетів: додавання стилю та функціональності

Іноді стандартні віджети виглядають занадто простими. Ви ж не хочете, щоб ваша форма виглядала як сторінка Google 1999 року, правда? Тут на допомогу приходить можливість кастомізувати віджети.

Приклад 1: Додавання CSS-класів до віджета

Часто потрібно додати стиль до полів, наприклад, щоб вони виглядали гарно з Bootstrap. Це можна зробити через атрибут widget.

class StyledForm(forms.Form):
    name = forms.CharField(
        max_length=50,
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Введіть ваше ім'я'})
    )

У шаблоні:

<form method="post">
  {{ form.name }}
</form>

Результат:

<input type="text" name="name" class="form-control" placeholder="Введіть ваше ім'я">

Спочатку поле виглядає так, що здається: "Вау, тут попрацювала людина зі смаком!".

Приклад 2: Використання віджета для вибору дати

Поле для вибору дати (DateField) має звичайний віджет TextInput за замовчуванням. Але що, якщо ми хочемо календар, щоб спростити вибір дати?

class DateForm(forms.Form):
    birth_date = forms.DateField(
        widget=forms.DateInput(
            attrs={'type': 'date', 'class': 'form-control'}
        )
    )

На сторінці відобразиться поле з вбудованим календарем (якщо браузер підтримує <input type="date">).

Візуально: 🗓️ (десь у браузері Chrome).

Приклад 3: Кастомізація полів за допомогою JavaScript

Іноді одних тільки атрибутів HTML недостатньо. Наприклад, ви хочете додати інтерактивність, скажімо, відображення завантаження файлів або маску введення для телефонного номера. Для цього віджети підтримують додаткові атрибути.

Приклад:

class PhoneForm(forms.Form):
    phone_number = forms.CharField(
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Введіть телефон',
            'oninput': "this.value = this.value.replace(/[^0-9+() ]/g, '')"
        })
    )

Тепер при введенні користувач буде автоматично блокований від введення букв (JavaScript на сторожі!).

Створення користувацького віджета

Іноді стандартних віджетів недостатньо, і тоді можна створювати власні.

from django.forms.widgets import Widget
from django.utils.safestring import mark_safe

class CustomCheckbox(Widget):
    def render(self, name, value, attrs=None, renderer=None):
        return mark_safe(f'<input type="checkbox" name="{name}" value="{value}" class="custom-checkbox">')

class CustomWidgetForm(forms.Form):
    agree = forms.CharField(widget=CustomCheckbox())

Шаблон:

<form method="post">
  {{ form.agree }}
</form>

Результат: <input type="checkbox" name="agree" value="1" class="custom-checkbox">, з можливістю стилізації на ваш смак.

Практичне застосування: форма завантаження файлів

Допустимо, вам потрібно створити форму для завантаження фотографії профілю.

class FileUploadForm(forms.Form):
    photo = forms.ImageField(
        widget=forms.ClearableFileInput(attrs={
            'class': 'form-control',
            'accept': 'image/*'
        })
    )

Тут віджет ClearableFileInput додає функціональність для видалення раніше завантажених файлів.

У шаблоні:

<form method="post" enctype="multipart/form-data">
  {{ form.photo }}
</form>

Поради та типові помилки

  • Помилка: забули вказати атрибути. Наприклад, додали клас form-control до форми, але забули про placeholder, що зробило форму неінтуїтивною. Користувачі можуть не зрозуміти, що від них вимагається.
  • Помилка: несумісність віджетів із типом поля. Спроба використати DateInput для CharField викличе розрив шаблонів у вашому коді.
  • Помилка: відсутність базового розуміння JavaScript. Без нього віджети з фронтенд-логікою (наприклад, автозаповнення) працюють повільно або ламаються.

Чому це важливо

Розуміння віджетів допомагає створювати форми, які не лише функціональні, але й зручні для користувачів. Використовуючи віджети, ти можеш оптимізувати взаємодію користувача з системою та уникнути непорозумінь. У реальних проєктах це особливо важливо, адже форми — це основний спосіб "спілкування" між користувачем і твоїм застосунком.

Для детального вивчення віджетів ти можеш звернутися до офіційної документації Django.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ