2010-11-03 31 views
5

Ho bisogno di impostare il valore del campo, non passato al costruttore di Django Form.Imposta il valore del campo nel metodo Django Form clean(), se questo campo non è passato nel costruttore

devo modello e la forma in questo modo:

class Message(models.Model): 
    created  = models.DateTimeField() 
    text  = models.CharField(max_length=200, blank=True, null=True) 
    active  = models.BooleanField(default=False) 

class MessageForm(forms.ModelForm): 
    class Meta: 
     model = Message 
     exclude = ('created', 'active') 

    def clean(self): 
     # check if user is blocked 
     if user.is_admin(): 
      self.cleaned_data['active'] = True 
     return self.cleaned_data 

Expected: se l'utente corrente è admin - devo inserire automaticamente un messaggio come attivo. L'utente non deve passare questo parametro per forma.

effettivo: vedo che il messaggio salvato ha sempre il flag "False" (posso eliminare la condizione e in questo caso vedo anche che il messaggio non è attivo).

Ti prego, aiutami a capire, come posso fare impostare questa "attiva" bandiera pulito metodo().

+1

Come e da dove viene la variabile "utente" Get Set? –

+0

I bianco questo per esempio. È possibile eliminare questa condizione o sostituirla con qualcos'altro. Ho impostato self.cleaned_data ['active'] = True, ma ho anche bisogno di dire a Django Form che questo campo è usato e che è necessario impostare questo valore sull'oggetto prima di salvare. Posso farlo con il parametro "iniziale" per l'oggetto Form, ma non posso farlo nel mio caso. Ho bisogno di dire a Django Form che ho usato il campo "attivo", ma non so come farlo in un metodo di compilazione clean(). –

risposta

4

La risposta precedente funzionerebbe, ma mi piace incapsulare tutte le operazioni interne del modulo come cosa mostrare e cosa no, all'interno del modulo. So che hai detto che non vuoi inviare un valore di campo al costruttore, ma se non ti dispiace inviare l'utente, la tua soluzione funzionerebbe. vale a dire, il vostro costruttore:

def __init__(self, user): 
    self.user = user 
    super(BaseForm, self).__init__() 

poi nella vostra pulito, basta cambiare il user-self.user. C'è un altro vantaggio aggiunto a questo. Dì che domani vuoi assegnare più campi in base al tuo utente, non devi aggiungere nulla alle viste, puoi semplicemente aggiungerlo al modulo.

MODIFICA: Quando si aggiunge un campo da escludere, non è disponibile nei dati puliti. Invece, imposta il suo widget come nascosto.

active = forms.BooleanField(widget=forms.HiddenInput) 

EDIT 2: Se davvero non si desidera che il campo in forma In questo caso, invece di sovrascrivendo il pulito, perché non si sovrascrive il salvataggio?

def save (self): 
    super(BaseForm, self).save() 
    if user.is_admin(): 
     self.instance.active=True 
    super(BaseForm, self).save() 
+0

Oggetto utente: questo non è un problema. Il problema non è impostato clean_data per l'oggetto salvato. Se imposto self.cleaned_data ['active'] = True nel risultato questo campo non è interessato. Ho bisogno di dire a Form che ho usato il campo "attivo" in questo processo di elaborazione, come i dati iniziali passati nel costruttore di moduli. –

+0

Appena ricontrollato il modulo. Il problema è che quando si esclude un campo in un modulo, non è disponibile nei dati puliti. Invece, includi l'attributo e imposta il suo widget su nascosto. controlla la mia modifica – zsquare

+0

Ho impostato i dati su self.cleaned_data - questo è bene. Ma ho bisogno di dire a Django Form di usare questo campo. Come fare questo? –

3

Non eseguire questa operazione nel metodo clean() del modulo, eseguire questa operazione nella vista.

def your_view(request): 
    if request.method == 'POST': 
     form = MessageForm(data=request.POST) 
     if form.is_valid(): 
      new_message = form.save(commit=False) 
      if user.is_admin(): 
       new_message.active = True 

Tuttavia, se si vuole anche per gestire il caso in cui l'utente è non amministratore utilizzando lo stesso modulo, si può guardare a incorporare logica simile a init del form() al posto della vista, probabilmente da passare informazioni sull'utente dalla vista a init() del modulo

+0

Descritto di seguito che ho bisogno di farlo nella logica del modello o nella logica del modulo. Nella vista - questo modo semplice non per il mio compito. Se l'utente lavora nella sezione di amministrazione, ho bisogno di attivare la mia logica personalizzata. Se faccio questa logica in vista - questo non funziona in tutti gli altri posti - e questo non è un bene! –

0

Utilizzare questa:

def message_form_factory(user): 
    class MessageForm(forms.ModelForm): 
     def clean(self): 
      # check if user is blocked 
      if user.is_admin(): 
       self.cleaned_data['active'] = True 
      return self.cleaned_data 
    return MessageForm 

E nel vostro uso di vista:

form = message_form_factory(request.user)() 
form = message_form_factory(request.user)(request.POST) 
+0

In Django admin ho bisogno di usare funzionale con logica personalizzata. La tua soluzione può essere utilizzata in admin con un modulo personalizzato, ma questo codice aggiuntivo attorno al progetto. Penso che questa non sia una buona soluzione nel mio caso. Grazie! –

+0

Per quanto posso leggere, non hai menzionato nulla sull'amministratore di Django nella tua domanda .. –

Problemi correlati