2012-01-18 18 views
29

Im intentando aprender vistas basadas en clases, para una vista detallada o de lista no es tan complicado.¿Cómo procesar un formulario (a través de get o post) usando vistas basadas en clases?

Tengo un formulario de búsqueda y solo quiero ver si envío una consulta para mostrar los resultados.

Aquí está el código de función (no es mío, es de un libro de Django):

def search_page(request): 
    form = SearchForm() 
    bookmarks = [] 
    show_results = False 
    if 'query' in request.GET: 
     show_results = True 
     query = request.GET['query'].strip() 
     if query: 
      form = SearchForm({'query': query}) 
      bookmarks = Bookmark.objects.filter(title__icontains=query)[:10] 


    show_tags = True 
    show_user = True 

    if request.is_ajax(): 
     return render_to_response("bookmarks/bookmark_list.html", locals(), context_instance=RequestContext(request)) 
    else: 
     return render_to_response("search/search.html", locals(), context_instance=RequestContext(request)) 

Ignorando el hecho de Ajax (sólo para simplificar el problema por ahora), ¿cómo puedo traducir esto a la clase ¿puntos de vista basados?

rápida que hemos probado algo como esto:

class SearchPageView(FormView): 
    template_name = 'search/search.html' 

    def get(self, request, *args, **kwargs): 
     form = SearchForm() 
     self.bookmarks = [] 
     self.show_results = False 
     if 'query' in self.request.GET: 
      self.show_results = True 
      query = self.request.GET['query'].strip() 
      if query: 
       form = SearchForm({'query': query}) 
       self.bookmarks = Bookmark.objects.filter(title__icontains=query)[:10] 
     return super(SearchPageView, self).get(request, *args, **kwargs) 

    def get_context_data(self, **kwargs): 
     context = super(SearchPageView, self).get_context_data(**kwargs) 
     context.update({ 
      'show_tags': True, 
      'show_user': True, 
      'show_results': self.show_results, 
      'bookmarks': self.bookmarks 
     }) 
     return context 

no funciona, me sale un "objeto 'NoneType' no es exigible"

Justo lo suficiente, empecé hoy con estas cosas.

Entonces, ¿cuál es la manera de hacer una vista basada en clase que pueda administrar una solicitud get (y una publicación también si es necesario)?

tengo otro ejemplo:

@render_to('registration/register.html') 
def register_page(request): 
    if request.method == 'POST': 
     form = RegistrationForm(request.POST) 
     if form.is_valid(): 
      user = User.objects.create_user(
       username=form.cleaned_data['username'], 
       password=form.cleaned_data['password1'], 
       email=form.cleaned_data['email'] 
      ) 
      return HttpResponseRedirect('/accounts/register/success/') 
    else: 
     form = RegistrationForm() 
    return locals() 

sería esto "transformado" de la misma manera que la primera? O extienden diferentes Vistas?

Im confundido mucho. No sé si el primero es ProcessFormView y el segundo FormView o qué.

Gracias.

EDIT: Solución terminé con:

class SearchPageView(FormView): 
    template_name = 'search/search.html' 

    def get(self, request, *args, **kwargs): 
     self.bookmarks = [] 
     self.show_results = False 
     form = SearchForm(self.request.GET or None) 
     if form.is_valid(): 
      self.show_results = True 
      self.bookmarks = Bookmark.objects.filter(title__icontains=form.cleaned_data['query'])[:10] 

     return self.render_to_response(self.get_context_data(form=form)) 


    def get_context_data(self, **kwargs): 
     context = super(SearchPageView, self).get_context_data(**kwargs) 
     context.update({ 
      'show_tags': True, 
      'show_user': True, 
      'show_results': self.show_results, 
      'bookmarks': self.bookmarks 
     }) 
     return context 

dejo esto aquí a alguien con la misma pregunta :)

+1

Copiar y pegar El objeto "NoneType" no se puede llamar "' no es muy útil. Si observa el número de línea en el rastreo, puede ver qué línea de código arroja la excepción, lo que podría ayudar para arreglarlo tú mismo. – Alasdair

+0

Pregunta actualizada, tenías razón, tenía que irme a la cama y pensé que necesitaba especificar mi clase de formulario y sí, tenías razón. –

Respuesta

23

El comportamiento por defecto de la clase FormView es para mostrar un formulario independiente para GET solicita y vincula el formulario para solicitudes POST (o PUT). Si la forma unida es válida, entonces el método form_valid se llama, que simplemente redirige a la URL éxito (definido por el atributo success_url o el método get_success_url.

Esto coincide con el ejemplo bastante bien. Es necesario reemplazar el método form_valid para crear el nuevo User, antes de llamar al método de la superclase para redirigir a la URL éxito.

class CreateUser(FormView): 
    template_name = 'registration/register.html' 
    success_url = '/accounts/register/success/' 
    form_class = RegistrationForm 

    def form_valid(self, form): 
     user = User.objects.create_user(
       username=form.cleaned_data['username'], 
       password=form.cleaned_data['password1'], 
       email=form.cleaned_data['email'] 
     ) 
     return super(CreateUser, self).form_valid(form) 

Su primer ejemplo no coincide con el flujo de FormView tan bien, porque no se está procesando un formulario con los datos POST, y no hace nada cuando el formulario es válido.

Podría intentar extender TemplateView, y poner toda la lógica en get_context_data. Una vez que funcione, puede factorizar el código que analiza los datos GET y devuelve los marcadores en su propio método. Puede consultar la extensión ListView, pero no creo que haya ninguna ventaja real a menos que quiera paginar los resultados.

+0

Funciona como un amuleto en este ejemplo (cambiando el nombre de los atributos: P) Pero sigo pensando que el primer ejemplo necesita una representación correcta de la vista basada en la clase. –

+1

Sí, buen lugar, he corregido los nombres de los atributos. – Alasdair

+0

¿Puede ayudarme por favor aquí? Cuando defina el objeto de usuario , ¿A dónde va después del método form_valid, es tan mágico para mí. – izdi

4

Nota, una respuesta aquí (Updating context data in FormView form_valid method?) resolvió este problema como este:

class ContextFormView(FormView): 
    template_name = 'some_template.html' 
    success_url = '...' 
    form_class = ClassOfTheForm 

    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, **kwargs) 
     else: 
      return self.form_invalid(form, **kwargs) 


    def form_invalid(self, form, **kwargs): 
     context = self.get_context_data(**kwargs) 
     context['form'] = form 
     # here you can add things like: 
     context[show_results] = False 
     return self.render_to_response(context) 

    def form_valid(self, form, **kwargs): 
     context = self.get_context_data(**kwargs) 
     context['form'] = form 
     # here you can add things like: 
     context[show_results] = True 
     return self.render_to_response(context) 

Esto funcionó perfecto para mí. (el mismo problema que en esta pregunta)

Como se mencionó anteriormente, esta no es mi solución, si quieres darle créditos a alguien, ve a la respuesta en el enlace y dale a esta persona los créditos. (Updating context data in FormView form_valid method?)

Cuestiones relacionadas