8👍
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!
38👍
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)
- Django test client response context None
- Apps aren't loaded yet exception occurs when using multi-processing in Django
- Django extract string from [ErrorDetail(string='Test Message', code='invalid')]
- Tracking changes to all models in Django
11👍
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.
- Django: JSON Notifications using Redis PubSub, Node.js & Socket.io
- How do you use Django-filter's '__in' lookup?
- Django rest framework model serializers – read nested, write flat
4👍
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.
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.
- How to debug Django custom management command using VS Code
- Using height_field and width_field attribute in ImageField of Django
- Cannot read property 'module' of undefined
- Override create method in django rest generics CreateAPIView
- Django models – assign id instead of object
0👍
I got into this problem and solve it with the following code, the answer by @jondykeman does not have pagination and other utilities for base classes. the other approaches that are proposed are a little complicated than the following:
class ObjectCreateView(LoginRequiredMixin, MultipleObjectMixin, View):
queryset = Wallet.objects.all()
def get(self, request):
self.object_list = super(ObjectCreateView, self).get_queryset().filter(user=request.user)
allow_empty = super(ObjectCreateView, self).get_allow_empty()
if not allow_empty:
if super(ObjectCreateView, self).get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists'):
is_empty = not self.object_list.exists()
else:
is_empty = not self.object_list
if is_empty:
raise Http404()
context = super(ObjectCreateView, self).get_context_data()
form = CreateObjectForm()
context['form'] = form
return render(request, 'objects/object-list.html', context=context)
def post(self, request):
form = CreateWalletForm(request.POST)
if form.is_valid():
Object.objects.create(name=form.cleaned_data['name'], user=request.user)
messages.success(request, 'Object is created')
else:
messages.error(request, utility.get_form_errors_as_string(form))
return redirect('objects:create')