Некоторое время назад мне нужно было сделать нечто подобное, и ниже описывается, чем мы в конечном итоге занимаемся.
У нас есть две таблицы: Item и UnfinishedItem. Когда пользователь заполняет данные с помощью мастера, данные сохраняются в таблице UnfinishedItem. На каждом шаге мастера сервер проверяет данные, введенные на этом шаге. Когда пользователь завершает работу с мастером, мастер отображает скрытую / доступную только для чтения форму на странице подтверждения, которая показывает все данные, подлежащие отправке. Пользователь может просмотреть эту страницу и вернуться к соответствующему шагу, чтобы исправить ошибки. Когда пользователь удовлетворен своими записями, он нажимает кнопку «Отправить», и мастер затем отправляет все данные в скрытых / доступных только для чтения полях формы на сервер API. Когда сервер API обрабатывает этот запрос, он повторно запускает все проверки, которые он выполнял на каждом шаге мастера, и выполняет дополнительные проверки, которые не вписываются в отдельные этапы (например, глобальные проверки, дорогостоящие проверки).
Преимущества двухстолового подхода:
в базе данных вы можете иметь более жесткие ограничения для таблицы Item, чем для таблицы UnfinishedItem; вам не нужно иметь дополнительные столбцы, которые действительно потребуются после завершения работы мастера.
Агрегировать запросы по готовым Элементам для отчетности проще, так как вам не нужно помнить, чтобы исключить UnfinishedItems. В нашем случае нам никогда не требовалось выполнять агрегированные запросы между Item и UnfinishedItems, так что это не проблема.
Недостаток:
- Это склонно к дублированию логики проверки. Веб-инфраструктура, которую мы использовали, Django, делает это немного более терпимым, так как мы использовали наследование модели с небольшим количеством мета-магии, чтобы изменить ограничения, которые должны быть разными в Item и UnfinishedItem. Django генерирует большую часть базы данных и формы проверки из модели, и нам нужно только взломать несколько дополнительных проверок поверх этого.
Другие возможности, которые я рассмотрел, и почему мы не пошли с ними:
- сохранение данных в файлах cookie или локальном хранилище: пользователь не может продолжить отправку с другого устройства или удалить историю браузера.
- сохранить UnfinishedItem как неструктурированные данные (например, JSON) в базе данных или вторичном хранилище данных: мне придется определить логику синтаксического анализа и не могу использовать автоматическую проверку модели / формы Django.
- сделайте проверку за шаг на стороне клиента: мне придется продублировать логику проверки между Python / Django и JavaScript.