2011-08-02 11 views
12

Tengo una clase QuestionView que se deriva de la clase FormView. Aquí es un fragmento de código para explicar mi problema:¿Actualizar datos de contexto en el método FormView form_valid?

class QuestionView(FormView): 
    ... 
    context_var1 = y 
    def form_valid (self, form): 
    ... 
    self.context_var1 = x 
    ... 
    def get_context_data(self, **kwargs): 
    ... 
    context['context_var1'] = self.context_var1 
    ... 
    return context 

Como se muestra arriba, actualizar un conjunto de variables de contexto en form_valid y tengo la intención de utilizar los valores actualizados de estos en la plantilla - por lo tanto las variables de el diccionario context. El problema con este código es que no se ve el cambio en context_var1, podría ser porque get_context_data es llamado antes del método form_valid. ¿Hay una solución para esto?

Respuesta

25

Hago esto con form_invalid. He aquí cómo lo hago:

from django.views.generic import FormView 

class ContextFormView(FormView): 
    def get(self, request, *args, **kwargs): 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     context = self.get_context_data(**kwargs) 
     context['form'] = form 
     return self.render_to_response(context) 

    def post(self, request, *args, **kwargs): 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     if form.is_valid(): 
      return self.form_valid(form) 
     else: 
      return self.form_invalid(form, **kwargs) 

    def form_invalid(self, form, **kwargs): 
     context = self.get_context_data(**kwargs) 
     context['form'] = form 
     return self.render_to_response(context) 

Puede hacer lo mismo pero para form_valid. Normalmente el cuerpo de form_valid se parece a esto:

def form_valid(self, form): 
    return HttpResponseRedirect(self.get_success_url()) 

que tendría que anular tanto post y form_valid, ya post llamadas form_valid.

def post(self, request, *args, **kwargs): 
    form_class = self.get_form_class() 
    form = self.get_form(form_class) 
    if form.is_valid(): 
     return self.form_valid(form, **kwargs) 
    else: 
     return self.form_invalid(form, **kwargs) 

def form_valid(self, form, **kwargs): 
    # take some other action here 
    return HttpResponseRedirect(self.get_success_url()) 

ah y sólo para aclarar, la razón de ser de este problema es que el método de la clase getProcessFormView está roto. Normalmente se ve así:

def get(self, request, *args, **kwargs): 
    form_class = self.get_form_class() 
    form = self.get_form(form_class) 
    return self.render_to_response(self.get_context_data(form=form)) 

Sólo los tiros de distancia kwargs (._.)

+2

Gracias por la solución. Dos años más tarde, Django todavía no proporciona una forma de actualizar el contexto en form_valid o form_invalid. – pymarco

+0

Y tampoco en django 1.7 :( – vinyll

+1

Do Django 1.8 proporciona una forma de actualizar el contexto en form_valid? –

0

Tal vez usted puede utilizar este enfoque:

class SomeView(View): 

    def post(self, request): 
     my_form = MyForm(request.POST) 
     if my_form.is_valid(): 
      context['foo'] = 'bar' 

     return render(request, 'valid/path.html', context) 
1

En views.py

class UploadTest(FormView): 
    template_name = 'test.html' 
    .... 
    plus_context = dict() 

    def form_valid(self, form): 
     ... 
     self.plus_context['you_want_context'] = value 
     ... 
     return super(UploadTest, self).form_valid(form) 

    def get_context_data(self, **kwargs): 
     context = super(UploadTest, self).get_context_data(**kwargs) 
     context['plus_context_key'] = self.plus_context 
     return context 

En test.html

<html> 
    .... 
    <body> 
    .... 
    // first post can not get plus_context_key 
    {% if plus_context_key %} 
     {{ plus_context_key.you_want_context }} 
    {% endif %}  
    </body> 
</html> 

Me acabo de dar cuenta de esto en Django 1.10.3. Espero que pueda ayudarlo

+0

En caso de que el formulario se redirija a sí mismo, esto mostraría el contenido 'plus_context_key' incluso con un' GET' en la vista de formulario. Para evitar esto, use 'self.plus_context = dict()' después de 'context ['plus_context_key'] = self.plus_context' para restablecer el resultado para cualquier' GET' posterior – shadi

0

En Django 2.0.1 puede insertar datos de contexto sobrescribiendo get_context_data o form_invalid.

En su caso, usted podría hacer una de las siguientes sustituciones:

class QuestionView(FormView): 
    ... 

    def form_invalid(self, form): 
     """If the form is invalid, render the invalid form.""" 
     return self.render_to_response(
      self.get_context_data(
       form=form, 
       context_key=some_value 
      ) 
     ) 

O:

class QuestionView(FormView): 
    ... 

    def get_context_data(self, **kwargs): 
     if 'context_key' not in kwargs: # set value if not present 
      kwargs['context_key'] = some_value 
     return super().get_context_data(**kwargs) 

Django 2.0.1 insertos bajo el capó en forma de los kwargs get_context_data.

# File: django.views.generic.edit 

class FormMixin(ContextMixin): 
    ... 

    def form_valid(self, form): 
     """If the form is valid, redirect to the supplied URL.""" 
     return HttpResponseRedirect(self.get_success_url()) 

    def form_invalid(self, form): 
     """If the form is invalid, render the invalid form.""" 
     return self.render_to_response(self.get_context_data(form=form)) 

    def get_context_data(self, **kwargs): 
     """Insert the form into the context dict.""" 
     if 'form' not in kwargs: 
      kwargs['form'] = self.get_form() 
     return super().get_context_data(**kwargs) 
Cuestiones relacionadas