2012-04-05 9 views
5

Stiamo costruendo una procedura guidata utilizzando la nuova funzionalità di creazione guidata form di Django 1.4.
I documenti su questo sono molto concisi e non possiamo trovare esempi avanzati. Stiamo usando una procedura guidata con nome (necessaria per supportare un listview/datagrid che usiamo) e un back-end di sessione. La procedura guidata è pensata per modificare ruoli e diritti collegati ed è progettata per fornire sia funzionalità di aggiunta che modifica. Facciamo questo chiedendo all'utente nel primo passaggio se lui/lei vuole aggiungere o modificare.Hai bisogno di chiarimenti sull'utilizzo di Wizard forma Django 1.4, in particolare pre-riempimento e salvataggio

Il passaggio successivo dipende da tale scelta; Se l'utente desidera modificare, c'è una schermata di ricerca, seguita da uno listview/datagrid che visualizza i risultati. L'utente può quindi selezionare uno dei risultati e passare a uno schermo dei dettagli, seguito da una pagina FilteredSelectMultiple, che gli consente di collegare i diritti a questo ruolo.

Se l'utente desidera aggiungere un nuovo ruolo, le schermate di ricerca e dei risultati vengono saltate e l'utente passa direttamente alla schermata dei dettagli, seguita dalla schermata di collegamento.
E tutti funziona abbastanza bene, con un condition_dict in urls.py, ma ci si chiede un paio di cose circa la funzionalità generale:

Quando si seleziona un ruolo specifico preesistente, come possiamo riempire il dettagli e lo schermo di collegamento con i dati corrispondenti?

Istanziamo un oggetto-ruoli e lo passiamo in qualche modo alle due forme, in tal caso, dove lo istanziamo e dobbiamo farlo per ogni forma separatamente (che sembra un po 'esagerato)?

Quando si salva, è pratica comune creare un'altra istanza di un oggetto ruolo, aggiungere i dati del modulo e salvare, oppure riutilizzare l'oggetto utilizzato nei moduli in qualche modo?

Abbiamo cercato di sovraccaricare get_form_instance di restituire istanze di ruoli, e abbiamo preso in considerazione instance_dict nella documentazione, ma ci si sente come l'approccio sbagliato e non ci sono esempi che si trovano on-line, e siamo non sono nemmeno sicuro che questi siano usati per pre-compilare i dati o anche se siamo sulla strada giusta.

Logicamente, direi nel passaggio che seleziona un ruolo esistente, ho bisogno di riempire le variabili guidate usando un'istanza dell'oggetto scelto, e queste vengono visualizzate nei moduli. Alla fine della procedura guidata invertiamo il processo e prendiamo tutti i dati dalle variabili della procedura guidata e li aggiungiamo a un oggetto-ruolo appena istanziato e lo salviamo. Idealmente, questa istanza si determinerà se è necessario eseguire un INSERT o un UPDATE, a seconda che la chiave promary sia piena o meno.

Se qualcuno può fornire un esempio o una spinta nella giusta direzione, sarebbe molto apprezzato.

Il codice della classe wizardview in views.py è qui sotto:

class RolesWizard(NamedUrlSessionWizardView): 

def get_template_names(self): 
    # get template for each step... 
    if self.steps.current == 'choice': 
     return 'clubassistant/wizard_neworeditrole.html' 
    if self.steps.current == 'search': 
     return 'clubassistant/wizard_searchrole.html' 
    if self.steps.current == 'results': 
     return 'clubassistant/wizard_pickrole.html' 
    if self.steps.current == 'details': 
     return 'clubassistant/wizard_detailsrole.html' 
    elif self.steps.current == 'rights': 
     return 'clubassistant/wizard_roles.html' 

def get_context_data(self, form, **kwargs): 
    # get context data to be passed to the respective templates 
    context = super(RolesWizard, self).get_context_data(form=form, **kwargs) 

    # add the listview in the results screen 
    if self.steps.current == 'results': 
     # get search text from previous step 
     cleaned_data = self.get_cleaned_data_for_step('search') 
     table = RolesTable(Roles.objects.filter(
      role_name__contains=cleaned_data['searchrole']) 
     ) 
     RequestConfig(self.request, paginate={ 
      "per_page": 4, 
      }).configure(table) 
     # add the listview with results 
     context.update({'table': table}) 

    # add a role instance based on the chosen primary key 
    if self.steps.current == 'rights': 
     cleaned_data = self.get_cleaned_data_for_step('results') 
     role_id = cleaned_data['role_uuid'] 
     role = get_object_or_404(Roles, pk=role_id) 
     context.update({'role': role}) 

    return context 

def done(self, form_list, **kwargs): 
    # this code is executed when the wizard needs to be completed 

    # combine all forms into a single dictionary 
    wizard = self.get_all_cleaned_data() 

    if wizard.get("neworeditrole")=="add": 
     role = Roles() 
    else: 
     role = get_object_or_404(Roles, pk=wizard.get("role_uuid")) 

    # many-to-many rights/roles 
    role.role_rights_new_style.clear() 
    for each_right in wizard.get('role_rights_new_style'): 
     RightsRoles.objects.create(role=role, right=each_right,) 

    # other properties 
    for field, value in self.get_cleaned_data_for_step('details'): 
     setattr(role, field, value) 

    role.save() 

    # return to first page of wizard... 
    return HttpResponseRedirect('/login/maintenance/roles/wizard/choice/') 

risposta

1

Vediamo se posso aiutare. Ho fatto un wizard di moduli che aggiunge passaggi a seconda delle risposte.Ad ogni passo li risparmio tutte le forme in una variabile di sessione, in questo modo:

def process_step(self, request, form, step): 
    request.session['form_list'] = self.form_list 
    request.session['initial'] = self.initial 

Poi, ogni volta che vista è reso, ho un'istanza di una nuova procedura guidata form con tutti i dati precedenti:

def dynamic_wizard(request): 
    if not request.session.get('form_list'): 
     form = Wizard([Form1]) 
    else: 
     form = Wizard(request.session.get('form_list'), initial = request.session['initial']) 
    return form(context=RequestContext(request), request=request) 
+0

Questo era django 1.3. – daigorocub

2

Per i googler del futuro:

Ho avuto qualche successo con l'utilizzo di get_form() perché è chiamato prima che un modulo sia reso. Inizia con un paio di ModelForms:

class Wizard1(models.ModelForm): 
    class Meta: 
     model = MyModel 
     fields = ('field0', 'model0') 
class Wizard2(models.ModelForm): 
    class Meta: 
     model = MyModel 
     excludes = ('field0', 'model0') 

Poi, nel vostro SessionWizardView:

class MyWizard(SessionWizardView): 
    def get_form(self, step=None, data=None, files=None): 
     form = super(ExtensionCreationWizard, self).get_form(step, data, files) 

     if step is not None and data is not None: 
      # get_form is called for validation by get_cleaned_data_for_step() 
      return form 

     if step == "0": 
      # you can set initial values or tweak fields here 

     elif step == "1": 
      data = self.get_cleaned_data_for_step('0') 
      if data is not None: 
       form.fields['field1'].initial = data.get('field0') 
       form.fields['field2'].widget.attrs['readonly'] = True 
       form.fields['field3'].widget.attrs['disabled'] = True 
       form.fields['model1'].queryset = Model1.objects.filter(name="foo") 

     return form 

L'azione è tutto in passaggio 1. È richiesta di dati dal punto 0 (che innesca un'altra chiamata al get_form convalidato () per il passaggio 0, quindi fai attenzione) e quindi puoi accedere ai valori impostati nel passaggio 0.

Ho inserito un paio di esempi di impostazioni che è possibile modificare sui campi. È possibile aggiornare un set di query per limitare i valori in un campo Choice o visualizzare di nuovo un valore ma renderlo di sola lettura. Un avvertimento che ho notato ... readonly non funziona su ChoiceField. Puoi renderlo disabilitato, ma il valore non viene propagato quando invii il modulo.

+0

Questo è il modo per farlo! – JeffC

+0

hmm, il metodo "get_form" è un po 'sfortunato, secondo me, dal momento che qualsiasi materiale relativo alla forma dovrebbe essere tenuto in classe. Un modo migliore è usare get_form_kwargs per impostare "flags" e quindi usarli per personalizzare i campi all'interno del metodo form init. – mariodev

Problemi correlati