问题
I built a listview which works fine and gives me exactly what I want.
In the template of this ListView I declared a form that points to a CreateView. The form is like so,
{% if user.is_authenticated %}
<form action="{% url 'post_wall' %}" method="POST">
{% csrf_token %}
<input type='text' name='body' />
<input type='hidden' name='from_user' value='{{ user.id }}' />
<input type='hidden' name='to_user' value='{{ to_user }}' />
<input type='submit' value='POST'/>
</form>
{% endif %}
the post_wall url corresponds to
url(r'accounts/post_wall', WallCreate.as_view(), name='post_wall'),
The url which contains the form is
url(r'accounts/wall/(?P<slug>\w+)/$', WallList.as_view(), name='wall'),
This calls the CreateView,
class WallCreate(CreateView):
model = WallPost
def get_success_url(self):
url = reverse('wall', kwargs={'slug': request.POST.to_user})
return HttpResponseRedirect(url)
This gives me a
TemplateDoesNotExist at /accounts/post_wall
users/wallpost_form.html
Shouldn't this be working properly as a post is sent to a CreateView? Or have I misunderstood something about CBVs?
回答1:
Yes, but all the form process will have to be made by the ListView itself. That is simple, considering you can inherit the behaviour from ModelFormMixin. You will only need one url (to the list view). The template will look like:
{% if user.is_authenticated %}
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type='submit' value='POST'/>
</form>
{% endif %}
And your view:
from django.views.generic.list import ListView
from django.views.generic.edit import ModelFormMixin
class ListWithForm(ListView, ModelFormMixin):
model = MyModel
form_class = MyModelForm
def get(self, request, *args, **kwargs):
self.object = None
self.form = self.get_form(self.form_class)
# Explicitly states what get to call:
return ListView.get(self, request, *args, **kwargs)
def post(self, request, *args, **kwargs):
# When the form is submitted, it will enter here
self.object = None
self.form = self.get_form(self.form_class)
if self.form.is_valid():
self.object = self.form.save()
# Here ou may consider creating a new instance of form_class(),
# so that the form will come clean.
# Whether the form validates or not, the view will be rendered by get()
return self.get(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
# Just include the form
context = super(ListWithForm, self).get_context_data(*args, **kwargs)
context['form'] = self.form
return context
来源:https://stackoverflow.com/questions/18664182/is-it-possible-to-have-a-form-in-a-listview-template