Давайте обобщим наши знания о 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-приложение.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ