'How to display a list of search results in Django 4
I'm writing a Django app to manage sales leads. From the template that lists a page of leads, I want to give the user the ability to search all leads using first name and last name as the search criteria. When I type in a last name and press enter, the page flickers but remains on the same page rather than the template I created to list the search results.
My views, urls, and templates are below. What have I missed?
views.py
class LeadsListView(ListView):
model = Lead
template_name = 'leads/list.html'
context_object_name = 'leads_list'
paginate_by = 10
def get_queryset(self):
return Lead.objects.order_by('id')
class LeadsSearchResultsView(ListView):
model = Lead
context_object_name = 'search_results'
template_name = 'leads/search_results.html'
paginate_by = 10
def get_queryset(self):
query = self.request.GET.get('q')
return Lead.objects.filter(
Q(last__icontains=query) | Q(first__icontains=query)
)
urls.py
from django.urls import path
from .views import LeadsListView, LeadsDetailView, LeadsCreateView
from .views import LeadsSearchResultsView
app_name = 'lead'
urlpatterns = [
path('', LeadsListView.as_view(), name='list'),
path('<int:pk>/', LeadsDetailView.as_view(), name='detail'),
path('', LeadsCreateView.as_view(), name='create'),
path('', LeadsSearchResultsView.as_view(), name='search_results'),
]
The template that (successfully!) lists the leads, list.html:
{% extends 'base.html' %}
{% block content %}
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
{% endif %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
{% endif %}
<form action="{% url 'lead:search_results' %}" method="get">
<input type="search" name="q" value="{{ request.GET.q }}" placeholder="Search by last name"
class="form-control">
</form>
</ul>
</nav>
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">Lead No.</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Phone</th>
<th scope="col">Email</th>
<th scope="col">Zip Code</th>
</tr>
</thead>
<tbody>
{% for lead in page_obj %}
<tr>
<td><a href="{% url 'lead:detail' lead.pk %}">{{ lead.pk }}</a></td>
<td>{{ lead.first }}</td>
<td>{{ lead.last }}</td>
<td>{{ lead.mobile }}</td>
<td>{{ lead.email }}</td>
<td>{{ lead.zipcode }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}
And finally, the template that should list the results of the search, but doesn't, search_results.html:
{% extends 'base.html' %}
{% block content %}
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</a>
</li>
{% endif %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true">»</span>
<span class="sr-only">Next</span>
</a>
</li>
{% endif %}
<form action="{% url 'lead:search_results' %}" method="get">
<input type="search" name="q" value="{{ request.GET.q }}" placeholder="Search by last name"
class="form-control">
</form>
</ul>
</nav>
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">Lead No.</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Phone</th>
<th scope="col">Email</th>
<th scope="col">Zip Code</th>
</tr>
</thead>
<tbody>
{% for lead in page_obj %}
<tr>
<td><a href="{% url 'lead:detail' lead.pk %}">{{ lead.pk }}</a></td>
<td>{{ lead.first }}</td>
<td>{{ lead.last }}</td>
<td>{{ lead.mobile }}</td>
<td>{{ lead.email }}</td>
<td>{{ lead.zipcode }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}
Solution 1:[1]
Below is your url.py file
urlpatterns = [
path('', LeadsListView.as_view(), name='list'),
path('<int:pk>/', LeadsDetailView.as_view(), name='detail'),
path('', LeadsCreateView.as_view(), name='create'),
path('', LeadsSearchResultsView.as_view(), name='search_results'),
]
Here, you are calling 3 different views class with the same url '' which is wrong.
You can correct the same and proceed further.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Subhash Tulsyan |
