Давайте узагальнимо наші знання про Django ModelForm і створимо кілька форм на основі моделей, а потім інтегруємо їх у функціональний Django-додаток. Ось наша послідовність дій:
- Створювати ModelForm для існуючих моделей.
- Інтегрувати форми у представлення.
- Налаштовувати шаблони для відображення та роботи з формами.
- Покращувати функціональність, використовуючи кастомні методи та правила валідації.
Реалізація проекту: Управління бібліотекою
Для практичного прикладу ми створимо простий додаток "Бібліотека", де користувачі зможуть управляти книгами та авторами. У нас буде дві моделі: Author і Book. Користувачі зможуть додавати авторів, вказувати книги, пов’язуючи їх з авторами, а також редагувати існуючі записи.
Крок 1: створення моделей
Для початку, давайте визначимо наші моделі:
# models.py
from django.db import models
class Author(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
date_of_birth = models.DateField()
def __str__(self):
return f"{self.first_name} {self.last_name}"
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books")
published_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)
def __str__(self):
return self.title
Спочатку ми створюємо таблиці для зберігання інформації про авторів і книги за допомогою класів Author і Book. Зв'язок між моделлю Book і Author створюється через ForeignKey.
Не забудьте виконати міграції після створення моделей:
python manage.py makemigrations
python manage.py migrate
Крок 2: створення ModelForm для моделей
Тепер створимо форми, які будуть відображати поля з наших моделей:
# forms.py
from django import forms
from .models import Author, Book
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ['first_name', 'last_name', 'date_of_birth']
widgets = {
'date_of_birth': forms.DateInput(attrs={'type': 'date'}),
}
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'published_date', 'isbn']
widgets = {
'published_date': forms.DateInput(attrs={'type': 'date'}),
}
За допомогою widgets ми кастомізували відображення поля дати, щоб користувачам було простіше його заповнювати (наприклад, використовуючи віджет вибору дати в браузері).
Крок 3: створення представлень
Тепер створимо представлення, які будуть обробляти форми. Ми будемо працювати з CreateView та UpdateView, щоб забезпечити можливість додавання та редагування даних.
# views.py
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic import ListView
from .models import Author, Book
from .forms import AuthorForm, BookForm
class AuthorListView(ListView):
model = Author
template_name = 'library/author_list.html'
context_object_name = 'authors'
class AuthorCreateView(CreateView):
model = Author
form_class = AuthorForm
template_name = 'library/author_form.html'
success_url = reverse_lazy('library:author-list')
class AuthorUpdateView(UpdateView):
model = Author
form_class = AuthorForm
template_name = 'library/author_form.html'
success_url = reverse_lazy('library:author-list')
class BookListView(ListView):
model = Book
template_name = 'library/book_list.html'
context_object_name = 'books'
class BookCreateView(CreateView):
model = Book
form_class = BookForm
template_name = 'library/book_form.html'
success_url = reverse_lazy('library:book-list')
class BookUpdateView(UpdateView):
model = Book
form_class = BookForm
template_name = 'library/book_form.html'
success_url = reverse_lazy('library:book-list')
Крок 4: налаштування маршрутів
Налаштуємо маршрути для наших сторінок:
# urls.py
from django.urls import path
from . import views
app_name = 'library'
urlpatterns = [
path('authors/', views.AuthorListView.as_view(), name='author-list'),
path('authors/add/', views.AuthorCreateView.as_view(), name='author-add'),
path('authors/<int:pk>/edit/', views.AuthorUpdateView.as_view(), name='author-edit'),
path('books/', views.BookListView.as_view(), name='book-list'),
path('books/add/', views.BookCreateView.as_view(), name='book-add'),
path('books/<int:pk>/edit/', views.BookUpdateView.as_view(), name='book-edit'),
]
Крок 5: створення шаблонів
Список авторів
<!-- templates/library/author_list.html -->
<h1>Список авторів</h1>
<a href="{% url 'library:author-add' %}">Додати автора</a>
<ul>
{% for author in authors %}
<li>
{{ author.first_name }} {{ author.last_name }}
(<a href="{% url 'library:author-edit' author.id %}">Редагувати</a>)
</li>
{% endfor %}
</ul>
Форма автора
<!-- templates/library/author_form.html -->
<h1>{% if object.pk %}Редагувати автора{% else %}Додати автора{% endif %}</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Зберегти</button>
</form>
Аналогічно створіть шаблони для списків Book та форм Book.
Крок 6: тестування проекту
Тепер можна тестувати додаток:
- Запустіть сервер розробки:
python manage.py runserver - Перейдіть на
/authors/для управління авторами. - Перейдіть на
/books/для управління книгами.
Крок 7: перевизначення методів
Додамо валідацію ISBN у формі BookForm:
# forms.py
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'published_date', 'isbn']
widgets = {'published_date': forms.DateInput(attrs={'type': 'date'})}
def clean_isbn(self):
isbn = self.cleaned_data.get("isbn")
if len(isbn) != 13:
raise forms.ValidationError("ISBN повинен містити 13 символів.")
return isbn
Помилки та поради
- Поширена помилка: забути вказати метод
POSTу шаблоні форми. У результаті дані не будуть надіслані. - Порада: завжди тестуйте свої форми перед інтеграцією в проєкт, щоб переконатися в коректній роботі валідації.
- Поширена помилка: не обробити винятки в методі
save(). Будьте готові до сценаріїв, коли дані не проходять валідацію.
Практичне завдання
- Додайте можливість видалення авторів і книг через представлення
DeleteView. - Реалізуйте кастомізацію відображення списку книг (наприклад, додайте фільтри або сортування).
Вітаю! Тепер ви впевнено працюєте з ModelForm і знаєте, як інтегрувати форми в повноцінний Django-додаток.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ