Había necesitado hacer algo similar hace algún tiempo, y lo siguiente describe con qué terminamos.
Tenemos dos tablas, Item y UnfinishedItem. Cuando el usuario completa los datos con el asistente, los datos se almacenan en la tabla UnfinishedItem. En cada paso del asistente, el servidor valida los datos ingresados durante ese paso. Cuando el usuario termina con el asistente, el asistente presenta un formulario oculto / de solo lectura en una página de confirmación que muestra todos los datos que se deben enviar. El usuario puede revisar esta página y volver al paso correspondiente para corregir errores. Una vez que el usuario está satisfecho con sus entradas, el usuario hace clic en enviar y el asistente luego envía todos los datos en los campos de formulario ocultos / de solo lectura al servidor API. Cuando el servidor API procesa esta solicitud, vuelve a ejecutar todas las validaciones que realizó durante cada paso del asistente y realiza validaciones adicionales que no se ajustan a los pasos individuales (por ejemplo, validaciones globales, validaciones costosas).
Las ventajas del enfoque de dos tablas:
en la base de datos, puede tener restricciones más estrictas en la tabla Elemento que en la tabla UnfinishedItem; no tiene que tener columnas opcionales que realmente serán necesarias cuando el asistente haya finalizado.
Las consultas agregadas en los elementos terminados para generar informes son más fáciles, ya que no tiene que acordarse de excluir los UnfinishedItems. En nuestro caso, nunca tuvimos que hacer consultas agregadas entre Item y UnfinishedItems, por lo que esto no es un problema.
La desventaja:
- Es propenso a la duplicación de la lógica de validación. El marco web que utilizamos, Django, lo hace un poco más soportable ya que utilizamos la herencia de modelos con un poco de meta magia para cambiar las restricciones que necesitamos para ser diferentes en Item y UnfinishedItem. Django genera la mayor parte de la base de datos y la validación de formularios a partir del modelo, y solo necesitamos hackear algunas validaciones adicionales además.
Otras posibilidades que he considerado y por qué no fuimos con ellas:
- guardar los datos en cookies o almacenamiento local: el usuario no puede continuar su envío desde un dispositivo diferente o si elimina el historial de su navegador
- almacenar el UnfinishedItem como datos no estructurados (por ejemplo, JSON) en la base de datos o en el almacén de datos secundario: tendré que definir la lógica de análisis y no puedo usar la validación automática de modelo / formulario de Django.
- haga la validación por paso en el lado del cliente: tendré que duplicar la lógica de validación entre Python / Django y JavaScript.