Jonas Fredriksson
Jonas Fredriksson

Reputation: 355

passing form arguments in django

I am trying to implement a simple search function in django but somehow I can't pass the argument from my template to my view function. I've got a key error: KeyError at /artdb/search/ because kwargs is empty:

url.py:

    path('search/',views.Search.as_view(),name='search'),

base,.html:

 <form class="form-inline my-2 my-lg-0" name="search" action="{% url 'artdb:search' %}" {{ form.as_p }} method="get">{% csrf_token %}
      <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search" value="{{seastr}}">
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit" value="{{seastr}}">Search</button>
    </form>

views.py:

class Search(ListView):
    print("class Search")
    model=Person
    template_name='artdb/search.html'
    context_object_name='ans'

def get_queryset(self):
    Pdb().set_trace()
    self.seastr=get_object_or_404(Person,name=self.kwargs['seastr'])
    return Person.objects.filter(seastr=self.seastr)

Upvotes: 0

Views: 183

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477607

You did not attach the name seastr to your <input> field:

<form class="form-inline my-2 my-lg-0" name="search" action="{% url 'artdb:search' %}" {{ form.as_p }} method="get">{% csrf_token %}
    <input name="seastr" class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search" value="{{seastr}}">
    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>

Notice the name="seastr" in the <input> tag.

GET parameters are not stored in self.kwargs, but in self.request.GET, so we can obtain the parameter with self.request.GET['seastr'].

Typically the page with the search bar, is the same as the one with the request, therefore the search request if frequently optional. So it might be useful to make filtering optional here:

class Search(ListView):
    model=Person
    template_name='artdb/search.html'
    context_object_name='ans'

    def get_queryset(self):
        q = self.request.GET.get('seastr')
        if q is not None:
            return Person.objects.filter(seastr=q)
        else:
            return Person.objects.all()

Finally note that the seastr parameter is not part of the context data. You can make this part of the context data, by patching it:

class Search(ListView):
    model=Person
    template_name='artdb/search.html'
    context_object_name='ans'

    def get_queryset(self):
        q = self.request.GET.get('seastr')
        if q is not None:
            return Person.objects.filter(seastr=q)
        else:
            return Person.objects.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['seastr'] = self.request.GET.get('seastr')
        return context

Upvotes: 1

Related Questions