Джанго - Смешивание ListView и CreateView - PullRequest
12 голосов
/ 18 февраля 2012

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

Я могу заставить ее работать, используя 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 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'

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

Ответы [ 4 ]

29 голосов
/ 14 октября 2012

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

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)
11 голосов
/ 18 февраля 2012

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

Представление списка отображает список и веб-форму с action URLуказывая на создать представление .
Создать представление принимает данные POST и

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

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

8 голосов
/ 19 февраля 2012

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

  • ListView и CreateView - это «высокоуровневый» миксин, который агрегирует «нижний» "низкоуровневые" миксины. Но эти низкоуровневые миксины несовместимы друг с другом.
  • Класс View вызывает напрямую render_to_response (), но в моем сценарии есть 2 класса представления, и render_to_response () должен вызываться только один раз в конце.

Мне удалось «решить» эту проблему, выполнив следующие действия:

Вместо вызова ListView и CreateView я использовал миксины более низкого уровня. Более того, я явно вызвал BaseCreateView и BaseListView, из которых я «извлек» форму и список_объектов

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

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

4 голосов
/ 18 июня 2012

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

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

...