Ho avuto bisogno di fare qualcosa di simile qualche tempo fa, e quanto segue descrive quello che finiamo con.
Abbiamo due tabelle, Item e UnfinishedItem. Quando l'utente compila i dati con la procedura guidata, i dati vengono memorizzati nella tabella UnfinishedItem. Ad ogni passo della procedura guidata, il server convalida i dati immessi durante quel passaggio. Al termine della procedura guidata, la procedura guidata esegue il rendering di un modulo nascosto / di sola lettura in una pagina di conferma che mostra tutti i dati da inviare. L'utente può rivedere questa pagina e tornare alla fase pertinente per correggere gli errori. Una volta che l'utente è soddisfatto delle proprie immissioni, l'utente fa clic su Invia e la procedura guidata invia quindi tutti i dati nei campi modulo nascosto / di sola lettura al server API. Quando il server API elabora questa richiesta, esegue nuovamente tutte le convalide eseguite durante ogni fase della procedura guidata ed esegue ulteriori convalide che non rientrano nei singoli passaggi (ad esempio convalide globali, convalide costose). Al termine di tutte le convalide, il server API crea una voce nella tabella degli articoli.
I vantaggi dell'approccio a due tabelle:
-
nel database, puoi avere vincoli più stretti sulla tabella degli articoli rispetto alla tabella UnfinishedItem; non è necessario disporre di colonne facoltative che saranno effettivamente necessarie al termine della procedura guidata.
-
Le query aggregate sugli articoli finiti per la creazione di rapporti sono più facili in quanto non è necessario ricordare di escludere gli UnfinishedItems. Nel nostro caso, non abbiamo mai avuto bisogno di fare query aggregate tra Item e UnfinishedItems, quindi questo non è un problema.
Lo svantaggio:
- È soggetto a duplicazione della logica di convalida. Il framework web che abbiamo usato, Django, rende questo un po 'più sopportabile, poiché abbiamo usato l'ereditarietà del modello con un po' di meta magia per modificare i vincoli che dobbiamo essere diversi in Item e UnfinishedItem. Django genera la maggior parte del database e la convalida del modulo dal modello, e abbiamo solo bisogno di hackerare alcune convalide aggiuntive su di esso.
Altre possibilità che ho considerato e perché non siamo andati con loro:
- salvataggio dei dati nei cookie o nella memoria locale: l'utente non può continuare la propria trasmissione da un dispositivo diverso o se cancella la cronologia del browser
- memorizza l'UnfinishedItem come dati non strutturati (ad es. JSON) sul database o sul datastore secondario: dovrò definire la logica di analisi e non posso utilizzare la validazione automatica del modello / modulo di Django.
- fai la validazione per passo sul lato client: dovrò duplicare la logica di validazione tra Python / Django e JavaScript.