且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Django - 混合ListView和CreateView

更新时间:2023-12-04 09:44:04

我发现答案有两个问题:




  • ListView和CreateView是低级
    级别混合的高级混合。但是这些较低级别的混合不兼容。

  • View类直接调用render_to_response(),但在我的场景中,有2个视图类,render_to_response()只应该被调用一次$ / $>




    我能够解决这个问题,使用以下步骤:



    我使用较低级别的mixins而不是调用ListView和CreateView。另外我调用了显式的BaseCreateView和BaseListView,我从中提取窗体和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))

    它不干净,但它的作品!


    I'm want to create one page with a form, and every time I submit the form it adds an item to the list below the form.

    I can make it work using 2 pages:

    • one page using the mixin CreateView to add items
    • one page ListView to have the list.

    But I'm trying to have the form and the list on the same page. So I tried to create a class with both mixin:

    class FormAndListView(ListView, CreateView):
        pass
    

    Then I've used this class:

    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',)),
    

    But when I try to load the page, I get the 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'
    

    I've no idea how to debug that. Where to start?

    I found the answer, there is 2 problems:

    • ListView and CreateView are "high level" mixin which aggregate "lower level" mixins. But these lower level mixins are not compatible together.
    • The View class calls directly the render_to_response(), but in my scenario, there is 2 view class and render_to_response() should only be called once at the end.

    I was able "solve" this issue using the following steps:

    Instead of calling ListView and CreateView, I used lower level mixins. Moreover I called explicitly BaseCreateView and BaseListView from which I "extracted" the form and 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))
    

    It's not clean but it works!