Evan
Evan

Reputation: 2038

Django search form returning entire model

I'm trying to make a simple search form for class based views with Django. Everything seems to work, except the search result returns the entire model, so obviously the search/filter isn't working. I cannot figure out why after reading a bunch of tutorials and questions here.

models.py:

class surveys(models.Model):
    FAN = models.SlugField(max_length=100, blank=True, null=True)
    Location = models.CharField(max_length=200, blank=True, null=True)

    def __str__(self):
        return self.FAN

    def get_absolute_url(self):
        return reverse('survey-detail', args=[str(self.FAN)])

views.py:

class Search(generic.ListView):
    template_name = 'datalibrary/search.html'
    model = surveys

    def get_queryset(self):
        try:
            name = self.kwargs['name']
        except:
            name = ''
        if (name != ''):
            object_list = self.model.objects.filter(FAN__icontains == name)
        else:
            object_list = ''
        return object_list

class SearchResults(generic.ListView):
    template_name = 'datalibrary/search_results.html'
    model = surveys

search.html:

{% extends "base_generic.html" %}

{% block content %}
    <form method="get" action="/results/" class="navbar-form pull-right">
        <input type="text" id="searchBox" class="input-medium search-query" name="search" placeholder="Search">
        <input type="submit" class="btn" value="Search" >
    </form>
{% endblock %}

search_results.html:

{% extends "base_generic.html" %}

{% block content %} 
    {{ object_list }}
{% endblock %}

urls.py:

urlpatterns +=[
    path('search/', views.Search.as_view(), name='search'),
    path('results/', views.SearchResults.as_view(), name='search-results'),
]

Any idea why object_list returns all the values in the model rather filtering based on the input, even when there's no input?

Upvotes: 1

Views: 767

Answers (2)

Bidhan Majhi
Bidhan Majhi

Reputation: 1370

You have name = self.kwargs['name'], which does not getting any 'name', for search a better way is to take the input name as query and show the results.

class Search(generic.ListView):
    template_name = 'datalibrary/search.html'
    context_object_name = 'all_search_results'

    def get_queryset(self):
        result = super(Search, self).get_queryset()
        query = self.request.GET.get('search') #your input name is 'search'

        if query:
           object_list = surveys.objects.filter(FAN__icontains=query) #or FAN__contains
           result = object_list
        else:
           result = None    # When no result found

        return result

In Html,

{% extends "base_generic.html" %}

 {% block content %}
  <form method="get" action="/results/" class="navbar-form pull-right">
     <input type="text" id="searchBox" class="input-medium search-query" name="search" placeholder="Search">
     <input type="submit" class="btn" value="Search" >
  </form>



  {% for result in all_search_results %}
       {{result.add_according_to_the_model}}
  {% empty %}
        <p> No Results <p>
  {% endfor %}

   {% endblock %}

You can show search results in the same page. However if it is required for you then you can have different html.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599610

You're looking for something called self.kwargs['name'], but your view won't have any such item.

Firstly, the name of the search input in your HTML is search, not name.

And secondly, self.kwargs is for elements that are captured from the URL; but this is sent as a GET form, so you should get it from the querystring: self.request.GET['search'].

Putting it together, in a slightly more idiomatic way:

def get_queryset(self):
    name = self.kwargs.get('name')
    object_list = self.model.objects.all()
    if name:
        object_list = object_list.filter(FAN__icontains == name)
    return object_list

Upvotes: 1

Related Questions