Django - Mixing ListView and CreateView

后端 未结 4 1283
无人共我
无人共我 2020-12-14 11:55

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:

相关标签:
4条回答
  • 2020-12-14 12:12

    I use a lot of views that involve a form and a list of objects. Rather than trying to mixin things I just add the queryset into the context data as below.

    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)
    
    0 讨论(0)
  • 2020-12-14 12:14

    I have made my own class to solve this problem. I don't know if it's better or worse, but it works too. I have tried to use the generic mixins and have tested that validation and pagination work.

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

    If you try it and find any errors, please tell me here or in GitHub.

    0 讨论(0)
  • 2020-12-14 12:15

    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!

    0 讨论(0)
  • 2020-12-14 12:18

    Do not mix list and update views.
    Instead, create two separate views for these tasks:

    List view displays the list and a web form with action URL pointing to the create view.
    Create view accepts POST data and

    • displays form with error message in case of failure;
    • redirects to the list view in case of success.

    Also I've tried to use class-based views and found that they are too complex.
    I think it is much easier to use old-style function views.

    0 讨论(0)
提交回复
热议问题