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))
это не чисто, но это работает!
Я создал свой собственный класс для решения этой проблемы. Я не знаю, лучше это или хуже, но это тоже работает. Я попытался использовать общие миксины и протестировал эту работу проверки и разбиения на страницы.
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.