问题
I am trying to process two forms in a Django class based view. The site contains a form called form
(based on GET
) for narrowing the list results of the ListView and the second form status_form
(based on POST
).
Both forms are required since the ListView returns a list of items. Form
lets the user restrict the choices and status_forms
lets the user flag incorrect items via a modal form (therefore it needs to be in the same template).
My trouble is that ListView
does not come with the method post
, however FormView
does. My class List
inherits from both classes, but when I execute the class I get the error message:
Attribute Error: 'List' object has no attribute 'status_form'
How should I change my implementation to allow the second form been processed via the post method
?
class List(PaginationMixin, ListView, FormMixin):
model = ListModel
context_object_name = 'list_objects'
template_name = 'pages/list.html'
paginate_by = 10 #how may items per page
def get(self, request, *args, **kwargs):
self.form = ListSearchForm(self.request.GET or None,)
return super(List, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.status_form = StatusForm(self.request.POST or None)
if self.status_form.is_valid():
...
else:
return super(List, self).post(request, *args, **kwargs)
def get_queryset(self):
# define the queryset
...
# when done, pass to object_list
return object_list
def get_context_data(self, **kwargs):
context = super(List, self).get_context_data(**kwargs)
context.update(**kwargs)
context['form'] = self.form
context['status_form'] = self.status_form # Django is complaining that status_form is not existing, result since the post method is not executed
return context
回答1:
# Django is complaining that status_form does not exist,
# result since the post method is not executed
context['status_form'] = self.status_form
Because you didn't define self.status_from
in the first place.
You have defined it in get_context_data
, and it's accessible from there.
You can access you object from get_context_data
in your post method;
context = self.get_context_data(**kwargs)
status_form = context['status_form']
Also consider that you can define your status_form
directly in post
method itself without getting it from self
or get_context_data
.
Redesign you views to separate each Form processing in separate Views then tight them with each-other.
Views redesign:
In nutshell, let each view to do one job. You can create a View just for processing your status_form
and name it like StatusFormProcessView
then on your List
view return it on its post
method
class List(ListView);
def post(self, request, *args, **kwargs):
return StatusFormView.as_view()(request) # What ever you need be pass to you form processing view
This is just an example of it, need more work to be real.
For another example; On my website index page I have a search form. when user POST
or GET
the search form, The processing of searching doesn't exist in my IndexView
, instead I handle the whole form stuff in separate view, If form should process on GET
method, I'll override get()
method, If form should process on POST
, I'll override post()
method to send search_form
data to the view that is responsible for handling of processing the search_form
.
Comments response
status_form = context['status_form']
shouldn't it be
context['status_form'] = status_form
after I created it ?
You want to get status_form
from context
, So you need to
status_form = context['status_form']
Anyway, your form data are available on self.request.POST
来源:https://stackoverflow.com/questions/15622354/django-listview-with-post-method