2012-01-12 14 views
15

Vorrei fare un set di query in cui l'utente corrente viene utilizzata come filtro in una ModelForm:Come utilizzare la richiesta in un ModelForm in Django

class BookSubmitForm(ModelForm): 
    book = forms.ModelChoiceField(queryset=Book.objects.filter(owner=request.user),) 
... 

Vuol Django passare la richiesta al modulo? È una buona pratica? Come posso usare la richiesta? (Naturalmente la richiesta di nome non è definito)

Edit:

Ho provato un'altra soluzione è chiamare la forma nella visualizzazione passando richiesta:

form = BookSubmitForm(request) 

e poi nella forma Io uso questo:

class BookSubmitForm(ModelForm): 
    def __init__(self, request, *args, **kwargs): 
     super(BookSubmitForm, self).__init__(*args, **kwargs) 
     self.fields["library"].queryset = Library.objects.filter(owner=request.user) 

Funziona e il codice è nel modulo. Ora non sono sicuro che sia la soluzione migliore, potrebbe essere migliorata?

risposta

27

No, la richiesta non viene passata al ModelForm. Avrai bisogno di fare qualcosa di simile a suo avviso:

form = BookSubmitForm() 
form.fields['book'].queryset = Book.objects.filter(owner=request.user) 
# pass form to template, etc 

Come hai detto, è spesso più pulita racchiudendolo in oggetto Form, soprattutto se si dispone di diversi campi che dovranno set di query filtrati. Per fare questo, ignorare le di __init__() e farlo accettare una kwarg di request forme:

class BookSubmitForm(ModelForm): 
    def __init__(self, *args, **kwargs): 
     self.request = kwargs.pop("request") 
     super(BookSubmitForm, self).__init__(*args, **kwargs) 
     self.fields["book"].queryset = Book.objects.filter(owner=self.request.user) 
     self.fields["whatever"].queryset = WhateverModel.objects.filter(user=self.request.user) 

Poi basta passare richiesta ogni volta che un'istanza BookSubmitForm nella vista:

def book_submit(request): 
    if request.method == "POST": 
     form = BookSubmitForm(request.POST, request=request) 
     # do whatever 
    else: 
     form = BookSubmitForm(request=request) 
    # render form, etc 
+1

Hai ragione, funziona. Vorrei sapere se è possibile inserire il codice nel modulo, solo per scopi organizzativi e pulizia globale. – Bastian

+1

Sì, è possibile ed è spesso una buona idea per mantenere pulito il codice di visualizzazione. Ho aggiornato con un esempio. – AdamKG

0

Estendere AdamKG answer a vista base di classe - sovrascrivere il metodo get_form_kwargs:

class PassRequestToFormViewMixin: 
    def get_form_kwargs(self): 
     kwargs = super(PassRequestToFormViewMixin, self).get_form_kwargs() 
     kwargs['request'] = self.request 
     return kwargs 

from django.views.generic.edit import CreateView 
class BookSubmitCreateView(PassRequestToFormViewMixin, CreateView): 
    form_class = BookSubmitForm 
# same for EditView 

e poi in forme:

from django.forms import ModelForm 
class BookSubmitForm(ModelForm): 
    def __init__(self, *args, **kwargs): 
     self.request = kwargs.pop("request") 
     super(BookSubmitForm, self).__init__(*args, **kwargs) 
     ... 
Problemi correlati