Come creare percorsi diversi che gli utenti possono percorrere attraverso le pagine del mio sito?

6

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.

    
posta RexE 19.05.2013 - 12:08
fonte

4 risposte

8

Ho solo sfogliato i requisiti, ma pensavo a qualcosa di semplice come questo:

  1. Dai a ciascuna attività una lettera.
  2. Genera una stringa di sequenza di attività (ad es. EBDFA) per un utente.
  3. Guarda la prima lettera per decidere quale attività successiva.
  4. Esegui questo compito.
  5. Elimina la prima lettera, passa il resto nell'URL.
  6. vai al passaggio 3.

Mantengalo semplice. Non creare modelli che non ti servono, non memorizzare lo stato locale di cui non hai bisogno.

    
risposta data 03.06.2013 - 09:51
fonte
2

Dovrai raggruppare gli utenti in base alle assegnazioni di flusso. Per ogni gruppo di utenti hai una sequenza di pagine. Il modello di dati sarà quindi simile a

User     -->   UserGroup  <--  Sequences
+id            +id             +user_group_id
+name                          +current_step
+user_group_id                 +next_step

Su ogni singola pagina conosci l'id dell'utente e il passo corrente, così puoi facilmente recuperare il passo successivo per la situazione attuale.

    
risposta data 21.05.2013 - 17:03
fonte
1

Ci sono alcune domande che influenzeranno il design qui:

  1. Hai già informazioni che determineranno l'insieme / l'ordine dei compiti, o l'ordine sarà effettivamente casuale? In quest'ultimo caso, è possibile generare l'elenco delle attività quando si crea una nuova sessione e la si inoltra nei dati della sessione, insieme a un indicatore in cui è presente nell'elenco l'utente.
  2. Se hai già informazioni sul set / ordine delle attività, in che misura queste informazioni consistono in risposte / risultati dell'attività corrente? Se c'è una strong influenza nell'attività corrente nella selezione del prossimo, potresti stare meglio con un next_view_function per attività. Altrimenti, è possibile che una sia una classe base ereditata da tutti i controller di attività.

Aggiorna

In risposta all'aggiornamento: puoi codificare la sequenza nell'URL che hai assegnato (codifica base64 se non vuoi che sia troppo ovvio), oppure puoi memorizzare le informazioni nella sessione, come con il ordine casuale, tranne per il fatto che l'URL iniziale guida la generazione della sequenza, invece è casuale.

    
risposta data 19.05.2013 - 12:27
fonte
0

Mi sono imbattuto in una situazione come questa in un'applicazione che ho aiutato a creare.

L'ho chiamato User Sanity Test, perché stavo testando il modello User e gli stati possibili in cui poteva essere in relazione alle sue relazioni con altri modelli.

Le cose che avrei testato erano, se avessero impostato un indirizzo email, avessero i dettagli di fatturazione validi, hanno creato la loro prima cosa (tm), ecc.

Mi sono avvicinato a questo creando un middleware che eseguiva questi test su utenti autenticati, che utilizzavano la classe UserSanityTest e i feed nell'Utente corrente.

Se un test fallisce, restituisce un url al quale il middleware reindirizza l'utente.

Il controllo Sanity è attivo su tutti gli URL tranne quelli in SanityCheck.

Se l'utente sta visitando un Url SanityCheck che ha già soddisfatto, o li invia alla dashboard degli utenti o controlla gli altri SanityCheck e li elabora.

Gli URL normali descritti nel tuo UrlConf possono essere visitati solo quando tutti i SanityCheck sono completati.

    
risposta data 03.06.2013 - 08:09
fonte

Leggi altre domande sui tag