2012-02-18 37 views
9

Quiero crear una página con un formulario, y cada vez que envío el formulario agrega un elemento a la lista debajo del formulario.Django - Mezcla ListView y CreateView

puedo hacer que funcione por medio de 2 páginas:

  • una página utilizando el mixin CreateView para agregar elementos
  • una página ListView tener la lista.

pero estoy tratando de tener la forma y la lista en la misma página. Así que traté de crear una clase con tanto mixin:

class FormAndListView(ListView, CreateView): 
    pass 

Luego he utilizado esta clase:

FormAndListView.as_view(
    queryset=PdfFile.objects.order_by('id'), 
    context_object_name='all_PDF', 
    success_url = 'listview', 
    form_class = UploadFileForm, 
    template_name='textfrompdf/index.html',)), 

Pero cuando intento cargar la página, me sale el error: Exception Value: 'FormAndListView' object has no attribute 'object'

Traceback: 
File "C:\Program Files\Python_2.7\lib\site-packages\django\core\handlers\base.py" in get_response 
    111.       response = callback(request, *callback_args, **callback_kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in view 
    47.    return self.dispatch(request, *args, **kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in dispatch 
    68.   return handler(request, *args, **kwargs) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get 
    122.   return self.render_to_response(context) 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in render_to_response 
    94.    template = self.get_template_names(), 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get_template_names 
    134.    names = super(MultipleObjectTemplateResponseMixin, self).get_template_names() 
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\detail.py" in get_template_names 
    122.   if self.object and self.template_name_field: 

Exception Type: AttributeError at /PDF/ 
Exception Value: 'FormAndListView' object has no attribute 'object' 

No tengo idea de cómo depurar eso. ¿Donde empezar?

Respuesta

8

encontré la respuesta, hay 2 problemas:

  • ListView y CreateView son mixin "alto nivel" que agregado "inferiores nivel" mixins. Pero estas mixinas de nivel inferior no son compatibles entre sí.
  • La clase de vista llama directamente a render_to_response(), pero en mi escenario, hay 2 clases de vista y render_to_response() solo debe llamarse una vez al final.

yo era capaz de "resolver" este problema mediante los siguientes pasos:

En lugar de llamar ListView y CreateView, que utiliza mixins de nivel inferior.Por otra parte he llamado explícitamente BaseCreateView y BaseListView de la que "extraen" la forma y object_list

class FormAndListView(BaseCreateView, BaseListView, TemplateResponseMixin): 
    def get(self, request, *args, **kwargs): 
     formView = BaseCreateView.get(self, request, *args, **kwargs) 
     listView = BaseListView.get(self, request, *args, **kwargs) 
     formData = formView.context_data['form'] 
     listData = listView.context_data['object_list'] 
     return render_to_response('textfrompdf/index.html', {'form' : formData, 'all_PDF' : listData}, 
          context_instance=RequestContext(request)) 

No es limpia pero funciona!

+6

hay demasiado pasando con este punto de vista y que será difícil de MANTENER. El usuario 'jondykeman' tiene una solución más sana y más elegante para este problema. – zedr

8

No mezcle la lista y actualice las vistas.
su lugar, crear dos puntos de vista distintos para estas tareas:

al listado de las muestra la lista y un formulario web con action URL que apunta a la vista crear.
Crear vista acepta datos POST y

  • displays forman con el mensaje de error en caso de fallo;
  • redirige a la lista de ver en caso de éxito.

También he intentado utilizar vistas basadas en clases y he descubierto que son demasiado complejas.
Creo que es mucho más fácil usar vistas de funciones antiguas.

+1

Ho sí, buena idea! Voy a hacer eso, pero porque soy nuevo en Python y Django, me interesaría a entender por qué no funciona o bien cómo encontrar la fuente de mi error. ¡Gracias! – Nico

4

he hecho mi propia clase para resolver este problema. No sé si es mejor o peor, pero también funciona. He intentado usar las mezclas genéricas y he probado ese trabajo de validación y paginación.

The code in GitHub

class ListAppendView(MultipleObjectMixin, 
    MultipleObjectTemplateResponseMixin, 
    ModelFormMixin, 
    ProcessFormView): 
    """ A View that displays a list of objects and a form to create a new object. 
    The View processes this form. """ 
    template_name_suffix = '_append' 
    allow_empty = True 

    def get(self, request, *args, **kwargs): 
     self.object_list = self.get_queryset() 
     allow_empty = self.get_allow_empty() 
     if not allow_empty and len(self.object_list) == 0: 
      raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.") 
          % {'class_name': self.__class__.__name__}) 
     self.object = None 
     form_class = self.get_form_class() 
     form = self.get_form(form_class) 
     context = self.get_context_data(object_list=self.object_list, form=form) 
     return self.render_to_response(context) 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     return super(ListAppendView, self).post(request, *args, **kwargs) 

    def form_invalid(self, form): 
     self.object_list = self.get_queryset() 
     return self.render_to_response(self.get_context_data(object_list=self.object_list, form=form)) 

Si lo intenta y encuentra algún error, por favor dígame aquí o en GitHub.

27

que utilizan una gran cantidad de puntos de vista que implican una forma y una lista de objetos. En lugar de tratar de mezclar cosas, simplemente agrego el conjunto de preguntas en los datos de contexto como se muestra a continuación.

class UploadFileView(CreateView): 
    form_class = UploadFileForm 
    success_url = 'listview' 
    template_name = 'textfrompdf/index.html' 

    def get_context_data(self, **kwargs): 
     kwargs['object_list'] = PdfFile.objects.order_by('id') 
     return super(UploadFileView, self).get_context_data(**kwargs) 
+5

Esto es probablemente muy elegante, pero ayudaría a tener más explicación. – highpost

+0

¿Hay algún problema con tener bootstrap paginando la lista con este uso? – AlanSE