В современных веб-приложениях широко распространены веб-формы. Форма используется, когда мы хотим собирать данные (входные данные) от пользователей нашего приложения . В результате создается более динамичный веб-сайт, поскольку мы можем использовать собранную информацию для изменения веб-страницы.
Например, поисковая система, такая как Google, принимает данные от своих пользователей через веб-форму и настраивает свои результаты на основе информации. Кроме того, каждый сайт, который просит нас войти в систему, например GitHub, требует от нас предоставления нашего имени пользователя и пароля. Эта информация используется, чтобы определить, являемся ли мы подлинным пользователем или нет.
Кроме того, если мы хотим купить что-то в Интернете, например, на веб-сайте Amazon, нас просят ввести информацию о нашей кредитной карте.
Поскольку мы позволяем пользователям хранить книги в каталоге в рамках этого проекта, нам нужна веб-форма для сбора этой информации. Затем мы сохраняем его в базе данных, чтобы мы могли вернуть им книги.
Пример веб-формы
Ниже приведен пример веб-формы, написанной на HTML:
<form method="" action="">
<input type="text" name="name">
<input type="password" name="password">
<input type="submit" value="Submit">
</form>
В приведенном выше коде все поля ввода заключены в <form> тег. У <form> тега также есть два атрибута, которые мы рассмотрим, — method и action. Атрибут method определяет, как мы хотим, чтобы данные формы были отправлены. Как правило, веб-формы поддерживают два метода GET и POST.
Различие между ними заключается в том, что GET метод передает данные в качестве аргументов через URL-адрес и не должен использоваться для конфиденциальных данных. С другой стороны, метод POST передает данные в теле запроса.
Кроме того, большинство действий, которые редактируют или создают новые данные в базе данных, должны быть POST запросами. Как следует из названия, мы загружаем данные. Метод GET указывает, что мы ничего не изменяем, а только извлекаем данные.
К каждому полю ввода следует добавить атрибут . Это необходимо, чтобы найти определенное поле в нашем бэкэнде Django. Когда мы отправляем форму, она преобразуется в пару ключ-значение. Это name ключ, а значение — фактическое значение, введенное пользователем.
Наша форма также имеет action атрибут. Здесь мы указываем URL, на который должны быть отправлены данные формы для обработки. Он отправляется на текущую страницу, если она пуста. Если method атрибут оставлен пустым, GET метод используется по умолчанию.
Разработать тесты для форм
Мы продолжаем работать над проектом этого курса, написав тесты для нашей формы. Полный набор тестов можно найти ниже:
from django.test import TestCase, SimpleTestCase
from .models import Catalog
from django.urls import reverse
from django.urls.base import resolve
from .views import home
from .forms import AddBookForm
class CatalogFormTests(SimpleTestCase):
""" Тесты для форм """
def setUp(self):
url = reverse('home')
self.response = self.client.get(url)
def test_book_form(self):
form = self.response.context.get('add_book_form')
self.assertIsInstance(form, AddBookForm)
self.assertContains(self.response, 'csrfmiddlewaretoken')
def test_bootstrap_class_used_for_default_styling(self):
form = self.response.context.get('add_book_form')
self.assertIn('class="form-control"', form.as_p())
def test_book_form_validation_for_blank_items(self):
add_book_form = AddBookForm(
data={'title': '', 'ISBN': '', 'author': '', 'price': '', 'availability': ''}
)
self.assertFalse(add_book_form.is_valid())
class ElibraryURLsTest(SimpleTestCase):
""" Тестируем URLs """
def test_homepage_url_name(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, 200)
def test_root_url_resloves_to_homepage_view(self):
found = resolve('/')
self.assertEquals(found.func, home)
class CatalogModelTests(TestCase):
""" Тест модели каталога """
def setUp(self):
self.book = Catalog(
title='First Django Book',
ISBN='978-1-60309-3',
author='Ilya Perminov',
price='9.99',
availability='True'
)
def test_create_book(self):
self.assertIsInstance(self.book, Catalog)
def test_str_representation(self):
self.assertEquals(str(self.book), "First Django Book")
def test_saving_and_retrieving_book(self):
first_book = Catalog()
first_book.title = 'First Django Book'
first_book.ISBN = '978-1-60309-3'
first_book.author = 'Ilya Perminov'
first_book.price = '9.99'
first_book.availability = 'True'
first_book.save()
second_book = Catalog()
second_book.title = 'Second Django Book'
second_book.ISBN = '978-3-60124-1'
second_book.author = 'Dmitry Seleznev'
second_book.price = '19.99'
second_book.availability = 'False'
second_book.save()
saved_books = Catalog.objects.all()
self.assertEqual(saved_books.count(), 2)
first_saved_book = saved_books[0]
second_saved_book = saved_books[1]
self.assertEqual(first_saved_book.title, 'First Django Book')
self.assertEqual(second_saved_book.author, 'Dmitry Seleznev')
Посмотрим, что нового внутри test.py файла:
- Строка 9: Здесь мы видим класс формы
CatalogFormTests. Он является производным отSimpleTestCaseкласса, потому что нет взаимодействия с базой данных.
- Строка 15: Здесь мы видим наш первый тестовый метод
test_book_form. Этот метод проверяет общую форму, которая будет использоваться для добавления книги в каталог.
- Строка 16: Сначала мы получаем саму форму. Мы называем его
add_book_form. Получив это, мы сохраняем его в переменной с именемformи проверяем, что мы используем тот же экземпляр формы в нашем шаблоне, который в данном случае является домашней страницей.
- Строка 18: Мы дважды проверяем, включен ли токен CSRF. Следует отметить, что он должен быть включен в любую форму, обрабатывающую запрос POST.
- Строка 20: цель следующего тестового метода, который можно увидеть в этой строке, — убедиться, что мы правильно стилизовали форму. Мы будем использовать bootstrap в качестве стиля по умолчанию в будущем. Для этого мы ищем
form-controlкласс в полях ввода формы.
- Строка 24: Последняя тестовая функция позволяет нам убедиться, что пользователи не могут отправлять пустые данные формы без отображения соответствующих сообщений об ошибках.
Запускаем тесты
Пришло время запустить тесты после того, как они были написаны, чтобы убедиться, что они проваливаются. Поскольку второй этап в TDD заключается в выполнении теста, который мы только что разработали, поскольку он не работает, это показывает, что мы в некоторой степени добавляем новый контент. Для запуска теста выполните следующие действия:
Используйте следующие команды для независимого выполнения каждого метода тестирования:
-
python manage.py test elibrary_app.tests.CatalogFormTests.test_book_form
-
python manage.py test elibrary_app.tests.CatalogFormTests.test_bootstrap_class_used_for_default_styling
-
python manage.py test elibrary_app.tests.CatalogFormTests.test_book_form_validation_for_blank_items
Все тесты проваливаются, как и предполагалось, потому что мы еще не создали форму.