2011-04-27 18 views
12

Por lo tanto, mi objetivo es poder filtrar un conjunto de consulta ModelChoiceField en mi ModelForm para incluir únicamente los lugares que request.user ha creado.Enviando objeto request.user a ModelForm desde la vista genérica basada en clase en Django

Mi ModelForm es simplemente:

class PlaceEventForm(models.ModelForm): 
    class Meta: 
     model = Event 

me gustaría ser capaz de añadir algo como:

def __init__(self, *args, **kwargs): 
    super(PlaceEventForm, self).__init__(*args, **kwargs) 
    self.fields['place'].queryset = Place.objects.filter(created_by=request.user) 

Sin embargo, me parece que no puede encontrar una manera de acceder a la solicitud en el ModelForm.

mi opinión es de esta manera:

class PlaceEventFormView(CreateView): 
    form_class = PlaceEventForm 
    template_name = 'events/event_create.html' 

    @method_decorator(login_required) 
    def dispatch(self, *args, **kwargs): 
     return super(PlaceEventFormView, self).dispatch(*args, **kwargs) 

No estoy seguro si esto es ni siquiera cerca de lo que debería hacer, pero lo intentó:

def get_form_kwargs(self): 
    kwargs = super(PlaceEventFormView, self).get_form_kwargs() 
    kwargs.update({'place_user': self.request.user}) 
    return kwargs 

pero me dio el error: init() obtuvo un argumento de palabra clave inesperado 'place_user'

¿Tiene alguna idea sobre este tema? ¿O alguien puede pensar en una forma de filtrar mi ModelChoiceField en la vista sin tener que pasar mi pedido a ModelForm?

Respuesta

20

Necesitas pop clave user de kwargs en PlaceEventForm.__init__() método, para evitar que se va a ModelForm.__init__() método:

views.py:

class PlaceEventFormView(CreateView): 
    form_class = PlaceEventForm 
    template_name = 'events/event_create.html' 

    @method_decorator(login_required) 
    def dispatch(self, *args, **kwargs): 
     return super(PlaceEventFormView, self).dispatch(*args, **kwargs) 

    def get_form_kwargs(self): 
     kwargs = super(PlaceEventFormView, self).get_form_kwargs() 
     kwargs.update({'place_user': self.request.user}) 
     return kwargs 

forms.py:

class PlaceEventForm(models.ModelForm): 
    class Meta: 
     model = Event 

    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('place_user') 
     # now kwargs doesn't contain 'place_user', so we can safely pass it to the base class method 
     super(PlaceEventForm, self).__init__(*args, **kwargs) 
     self.fields['place'].queryset = Place.objects.filter(created_by=user) 
+0

Gracias mucho! Funciona perfectamente. – Brian

+0

Tiene problemas para entender cómo hacer esto. –

+0

Hice el ejemplo completo, avíseme si todavía no está claro –

1

Estoy en un iPhone, pero haz esto:

def get_form(self, form_class): 
    form = super(MyView, self).get_form(form_class) 
    form.fields['place'].querset = Place.... 
    return form 

¡Qué difícil! ¡Sin apoyo de indention!

0

Para actualizar la respuesta de Yuji para Django 1.10+ (incluido Django 2.0+), consulte el ejemplo siguiente (tenga en cuenta la firma del método actualizado). El enfoque sugerido de Yuji mantiene el conjunto de consulta en la vista junto con la otra lógica comercial, y ayuda a mantener cualquier clase de formulario que se extienda models.ModelForm limpia y directa.

def get_form(self, form_class=None): 
    if form_class is None: 
     form_class = self.get_form_class() 
    form = super(MyView, self).get_form() 
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user) 
    return form 

Shorter:

def get_form(self, form_class=None): 
    form = super(MyView, self).get_form(form_class) 
    form.fields['place'].queryset = Place.objects.filter(created_by=self.request.user) 
    return form 
Cuestiones relacionadas