2009-05-14 9 views
9

Ho un modello che ha un campo chiamato "stato":come modificare le scelte sulle pagine di amministrazione - Django

class Foo(models.Model): 
    ... 
    state = models.IntegerField(choices = STATES) 
    ... 

Per ogni stato, le scelte possibili sono un certo sottoinsieme di tutti gli Stati. Per esempio:

if foo.state == STATES.OPEN:  #if foo is open, possible states are CLOSED, CANCELED 
    ... 
if foo.state == STATES.PENDING: #if foo is pending, possible states are OPEN,CANCELED 
    ... 

Di conseguenza, quando i cambiamenti foo.state ad un nuovo stato, la sua serie di scelte possibili cambia.

Come posso implementare questa funzionalità su Aggiungi/modifica pagine di amministrazione?

risposta

9

È necessario use a custom ModelForm nella classe ModelAdmin per quel modello. Nel metodo __init__ l'usanza del ModelForm, è possibile impostare in modo dinamico le scelte per quel campo:

class FooForm(forms.ModelForm): 
    class Meta: 
     model = Foo 

    def __init__(self, *args, **kwargs): 
     super(FooForm, self).__init__(*args, **kwargs) 
     current_state = self.instance.state 
     ...construct available_choices based on current state... 
     self.fields['state'].choices = available_choices 

usereste in questo modo:

class FooAdmin(admin.ModelAdmin): 
    form = FooForm 
+0

Cosa succede nelle viste "aggiungi" per l'amministratore, dal momento che non c'è self.instance, non puoi dipendere dall'istanza per il filtraggio, sarebbe bello avere l'oggetto request lì –

+0

Sì, questo ModelForm dovrebbe gestire l'assenza di self.instance e impostare le scelte disponibili iniziali in modo appropriato. Non so perché l'oggetto richiesta sia rilevante, ma tu hai accesso ad esso in ModelAdmin.add_view (http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py# L704). –

+0

È possibile modificare le scelte nel modello stesso? Dopo tutto, le scelte SONO inizialmente specificate nel modello, quando si crea il campo. –

-1

Vedo cosa stai cercando di fare, ma perché non visualizzarli tutti e se la persona sceglie lo stato attuale (già impostato), non modificare nulla?

si potrebbe anche semplicemente costruire una vista con un modulo per fornire questa funzionalità

+0

questa è una possibilità, tuttavia non molto elegante e sicura. cambiando lo stato si attivano alcuni calcoli e le modifiche dei dati da apportare, quindi non voglio davvero fidarmi degli utenti, anche se sono amministratori. – shanyu

0

Questo mi sembra un lavoro per alcuni javascript. Si desidera che l'elenco di elementi in una casella di selezione cambi in base al valore di qualcos'altro, che è presumibilmente una casella di controllo o un pulsante di opzione. L'unico modo per farlo in modo dinamico - senza chiedere all'utente di salvare il modulo e ricaricare la pagina - sarebbe con javascript.

È possibile caricare un javascript personalizzato nella pagina di amministrazione di un modello utilizzando la classe Media di ModelAdmin, documentata here.

+1

No, sta cercando di impostare le scelte per il prossimo valore di un campo in base al valore corrente di quello stesso campo - una differenza fondamentale. Quindi cambiare le opzioni dinamicamente lato client non è rilevante; in effetti sarebbe molto confuso. –

12

Quando si crea una nuova interfaccia di amministrazione per un modello (ad esempio MyModelAdmin) esistono metodi specifici per sostituire le scelte predefinite di un campo. Per un generico choice field:

class MyModelAdmin(admin.ModelAdmin): 
    def formfield_for_choice_field(self, db_field, request, **kwargs): 
     if db_field.name == "status": 
      kwargs['choices'] = (
       ('accepted', 'Accepted'), 
       ('denied', 'Denied'), 
      ) 
      if request.user.is_superuser: 
       kwargs['choices'] += (('ready', 'Ready for deployment'),) 
     return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs) 

Ma si può anche ignorare le scelte per ForeignKey e Many to Many relazioni.

+3

Questa dovrebbe essere la risposta accettata in quanto è la soluzione più semplice e migliore. –

+0

@shanyu Questa dovrebbe essere la risposta accettata in quanto è il modo più pignolo per gestire il problema. – Jay

Problemi correlati