2012-02-18 70 views
9

我想與表單中創建一個頁面,每次我提交表單時它增加了一個項目的形式下面的列表。Django的 - 混合ListView和CreateView的

我可以使它工作使用2頁:使用

  • 一頁混入CreateView添加項目
  • 一個ListView頁面紛紛上榜。

但我想有形式和在同一頁上的列表中。所以,我試圖創建一個類既混入:

class FormAndListView(ListView, CreateView): 
    pass 

然後我用這個類:

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

但是,當我嘗試加載網頁,我得到的錯誤: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' 

我不知道如何調試。從哪兒開始?

回答

8

我找到了答案,有2個問題:

  • ListView和CreateView的是 「高層」 混入其中聚合 「下 級」 混入。但是這些較低級別的mixin不兼容。
  • View類直接調用render_to_response(),但在我的場景中,有2個視圖類,並且render_to_response()應該只在末尾調用一次。

我能 「解決」 使用以下步驟此問題:

而不是調用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)) 

這不是乾淨的,但它的工程!

+6

這個觀點太多了,這將是很難保持。用戶'jondykeman'對這個問題有一個更加清晰和更優雅的解決方案。 – zedr 2012-11-15 16:29:23

8

不要混合列表和更新視圖。
相反,創建這些任務兩個獨立的觀點:

列表視圖顯示列表,並與action URL指向創建視圖 Web表單。
創建視圖接受POST數據和

  • 顯示與在故障的情況下的錯誤消息形成;
  • 重定向到成功的情況下,列表視圖

另外我試過使用基於類的視圖,發現它們太複雜。
我認爲使用舊式功能視圖要容易得多。

+1

唔,好主意!我打算這麼做,但是因爲我對python和Django不熟悉,所以我有興趣瞭解它爲什麼不起作用或者如何找到我的錯誤的根源。謝謝! – Nico 2012-02-18 18:13:53

4

我已經讓自己的班級來解決這個問題。我不知道這是好還是壞,但它也能起作用。我試圖使用通用mixins並測試了驗證和分頁工作。

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

如果你嘗試一下,發現任何錯誤,請告訴我,在這裏或在GitHub上。

27

我使用了很多涉及窗體和對象列表的視圖。我沒有嘗試混入事物,而是將查詢集添加到上下文數據中,如下所示。

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

這可能非常優雅,但它會有助於有更多的解釋。 – highpost 2014-03-06 03:26:41

+0

有沒有用這個用法引導分頁列表的問題? – AlanSE 2015-06-25 19:15:02