Django-смешивание ListView и CreateView

Я хочу создать одну страницу с формой, и каждый раз, когда я отправить форму, он добавляет элемент в список ниже форма.

Я могу заставить его работать через 2 страницы:

  • одна страница с помощью mixin 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 FilesPython_2.7libsite-packagesdjangocorehandlersbase.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericbase.py" in view
  47.             return self.dispatch(request, *args, **kwargs)
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericbase.py" in dispatch
  68.         return handler(request, *args, **kwargs)
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericlist.py" in get
  122.         return self.render_to_response(context)
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericbase.py" in render_to_response
  94.             template = self.get_template_names(),
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericlist.py" in get_template_names
  134.             names = super(MultipleObjectTemplateResponseMixin, self).get_template_names()
File "C:Program FilesPython_2.7libsite-packagesdjangoviewsgenericdetail.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'

Я понятия не имею, как это отладить. С чего начать?

4 ответов


Я использую много представлений, которые включают форму и список объектов. Вместо того, чтобы пытаться смешивать вещи, я просто добавляю queryset в контекстные данные, как показано ниже.

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)

Не смешивать список и обновлять представления.
Вместо этого создайте два отдельных представления для этих задач:

посмотреть список отображает список и веб-форму с action URL, указывающий на создать вид.
создать вид принимает данные POST и

  • отображает форму с сообщением об ошибке в случае сбоя;
  • редирект на посмотреть список в случае успеха.

также я пытался использовать представления на основе классов и обнаружил, что они слишком сложны.
Я думаю, что гораздо проще использовать представления функций старого стиля.


Я нашел ответ, есть 2 проблемы:

  • ListView и CreateView-это" высокий уровень "mixin, который агрегирует" ниже уровень" миксины. Но эти миксины нижнего уровня несовместимы друг с другом.
  • класс представления вызывает непосредственно 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))

это не чисто, но это работает!


Я создал свой собственный класс для решения этой проблемы. Я не знаю, лучше это или хуже, но это тоже работает. Я попытался использовать общие миксины и протестировал эту работу проверки и разбиения на страницы.

код в 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.