Ho un sito web in cui gli utenti sono diretti a passare attraverso una sequenza di pagine per eseguire una sequenza di attività lavorative (trascrivere un paragrafo, rispondere a un sondaggio, interagire con un altro utente, ecc.). In breve, chiamiamo queste attività A, B, C, ecc. Sto usando Django e ogni attività è attualmente implementata come funzione di visualizzazione (o metodo), ad es. %codice%. Attualmente, ciascuna funzione di visualizzazione ha il passo successivo codificato in un reindirizzamento HTTP, ad es. def A(request)
.
La mia sfida è che presto avrò un requisito per creare varie permutazioni della sequenza di compiti. A volte voglio che gli utenti facciano A, B, C; per gli altri, B, C, D; per gli altri, A, B, D, F. Come posso progettare questo in modo da poter definire queste permutazioni in modo elegante e conciso nel mio codice? Intuitivamente, ho la sensazione di dover generalizzare le chiamate di reindirizzamento HTTP con una variabile, come: HttpResponseRedirect(reverse(B))
, ma faccio fatica a capire dove HttpResponseRedirect(reverse(next_view_function))
dovrebbe essere definito, e come la definizione della sequenza (ad esempio A, B, D) dovrebbe essere persistente tra le richieste.
Qualcuno può guidarmi lungo la strada giusta con un suggerimento o un'idea? Sono felice di fornire ulteriori dettagli.
Modifica in risposta alle domande di Bart:
- L'ordine dei compiti è predeterminato. Una volta definito, inviamo agli utenti un URL che li porta alla prima pagina. Dovrebbero quindi essere indirizzati attraverso le attività. Un gruppo di utenti potrebbe ottenere un URL che li porta attraverso i passaggi A, B, C, mentre un altro gruppo di utenti ottiene un URL che li porta attraverso i passaggi A, B, D. Decidiamo in anticipo quali utenti devono ottenere quale URL.
- Poiché l'ordine è predeterminato, il passaggio successivo non dipende dai risultati dell'attività corrente. L'unico requisito è per loro di completare l'attività (naturalmente convalidiamo i dati POST inviati come precondizione al reindirizzamento HTTP).
Modifica 2 , la mia soluzione finora:
Un concetto centrale nella mia architettura del codice è quello di un "Trattamento" (definito nel mio models.py). Un trattamento è una specifica dell'esperienza che un utente ha quando utilizza il mio sito, ad esempio quale interfaccia utente viene loro presentata. Ho diviso i miei utenti in gruppi e assegnato a ciascun gruppo un trattamento diverso inviando loro un URL contenente il PK del loro trattamento.
(Ci sono anche diverse sottoclassi di Trattamento, dal momento che alcuni Trattamenti sono completamente diversi dagli altri. SoccerTreatment e HockeyTreatment hanno poco in comune, quindi ha senso sottoclassarli.)
Quindi, la definizione di classe per un trattamento sembra essere il luogo sensato in cui archiviare la sequenza di viste come un elenco Python, come segue:
# in soccer/models.py
class SoccerTreatment(BaseTreatment):
world_cup = models.BooleanField()
....
def views(self, request):
seq = [soccer.views.ViewClassA]
if self.world_cup:
seq.append(soccer.views.ViewClassWorldCup)
return seq
# in shared/models.py
class BaseTreatment(models.Model):
def next_view(self, request):
seq = self.views() # views() method implemented by descendant classes
if request.session.get('current_view_index'):
request.session['current_view_index'] += 1
else:
request.session['current_view_index'] = 0
# [handle boundary cases, code snipped...]
# ...
return seq[request.session['current_view_index']]
# ...
# in views.py, at the end of a view function
# ...
HttpResponseRedirect(reverse(user.treatment.next_view()))
Tuttavia, il progetto di cui sopra non funzionerebbe, dal momento che models.py avrebbe dovuto importare views.py, creando un'importazione circolare. Quindi gli elementi della lista dovrebbero essere stringhe (o URL, o il nome della classe vista come una stringa), che potrebbe essere fragile dal momento che la ridenominazione delle mie classi o URL non rinominerà automaticamente queste stringhe.
Forse sono troppo pignolo, ma mi chiedo se c'è un design migliore.