2012-01-12 9 views
15

me gustaría hacer un conjunto de consultas, donde se utiliza el usuario actual como un filtro en un ModelForm:Cómo usar la solicitud en un ModelForm en Django

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

¿Se pasa Django la solicitud a la forma? ¿Es una buena práctica? ¿Cómo puedo usar la solicitud? (Por supuesto, la solicitud de nombre no está definido)

Editar:

Probé otra solución que es llamar a la forma en la vista pasándole la solicitud:

form = BookSubmitForm(request) 

y luego en la forma Yo uso esto:

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) 

Funciona y el código tiene el formato. Ahora no estoy seguro de que sea la mejor solución, ¿podría mejorarse?

Respuesta

27

No, la solicitud no se pasa al ModelForm. Tendrá que hacer algo como esto en su opinión:

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

Como usted ha dicho, a menudo es más limpio para encapsular esto en el objeto Form, sobre todo si tiene varios campos que necesitarán QuerySets filtrados. Para ello, anular de __init__() y haga que sea aceptar un kwarg de request las formas:

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) 

Entonces sólo tiene que pasar solicitud cada vez que una instancia BookSubmitForm en su opinión:

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

Tienes razón, funciona. Me gustaría saber si es posible poner el código en la forma, solo para fines de organización y limpieza global. – Bastian

+1

Sí, es posible y, a menudo, es una buena idea para mantener limpio el código de la vista. He actualizado con un ejemplo. – AdamKG

0

Extendiendo AdamKG answer a puntos de vista basados ​​clase - anular la get_form_kwargs método:

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 

y luego en formas:

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