Is it possible to have a form in a ListView templa

2019-02-20 06:27发布

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条回答
Emotional °昔
2楼-- · 2019-02-20 06:40

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
查看更多
登录 后发表回答