Reputation: 2038
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
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
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