Building a Video Sharing Website: Part 6 Adding a Video Search Bar

LegionScript
4 min readOct 20, 2020

Video Tutorial

Code on Github

In this tutorial, we will build the ability to search videos that are posted on the site. To do this, we will add a search bar inside a form to the navigation bar and then we will set up the action on the form to go to a new view that will filter based on what was typed into the search bar. We will add a url parameter to handle this. Let’s get started building this.

Add Search Bar to Navigation

This will be pretty simple. All we need to do is add a form inside of the nav bar, add a name attribute to the input field and set the action to a django url that we will create later. we will also use ionicons, which we used earlier, to add a magnifying glass button to the search bar.

Here is the navigation.html after the changes:

<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{% url 'index' %}">Video Sharer</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<form class="form-inline my-2 my-lg-0" method="GET" action="{% url 'video-search' %}">
<input class="form-control mr-sm-2" type="search" name="q" placeholder="Search" aria-label="Search" value="{{ request.GET.q }}">
<button class="search-button" type="submit"><ion-icon name="search-outline"></ion-icon></button>
</form>
<ul class="navbar-nav mr-auto">
</ul>
<ul class="navbar-nav">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'video-create' %}">Upload Video</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'account_logout' %}">Sign Out</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'profile' user.profile.pk %}"><img src="{{ user.profile.image.url }}" width="35" height="35" class="d-inline-block rounded-circle" alt="Profile"></a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'account_signup' %}">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'account_login' %}">Sign In</a>
</li>
{% endif %}
</ul>
</div>
</nav>

The name attribute is very important because that is what will be the name of the parameter that we will access later. With a GET request, the form data will be passed into the url which is what we want for this.

Next, we need to build the view for the search results. We need to get the search query by getting the q parameter from the GET request. We will use a Q object for a more complex query to sort by multiple different parts of the Video model. We will search by title, description, and the uploader username. From there, all we have to do is pass the resulting query list into the template.

from django.db.models import Qclass SearchVideo(View):
def get(self, request, *args, **kwargs):
query = self.request.GET.get("q")
query_list = Video.objects.filter(
Q(title__icontains=query) |
Q(description__icontains=query) |
Q(uploader__username__icontains=query)
)
context = {
'query_list': query_list,
}
return render(request, 'videos/search.html', context)

Now we need to build the template for this search result. There isn’t much to say about this, we just need to create something similar to the index view except our results will now only be what matches our query.

{% extends 'videos/base.html' %}{% block content %}
<div class="container">
<div class="row justify-content-center">
{% for object in query_list %}
<div class="card col-md-3 col-sm-12 mr-md-2 mt-5 p-3 border-0">
<a href="{% url 'video-detail' object.pk %}"><img src="/media/{{ object.thumbnail }}" width="256" height="144"></a>
<div class="card-body">
<a class="link-text" href="{% url 'video-detail' object.pk %}"><h5 class="text-center">{{ object.title }}</h5></a>
<p class="text-muted text-center m-0">{{ object.uploader }}</p>
<p class="text-muted text-center">{{ object.date_posted | date:"M d, Y" }}</p>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock content %}

Finally, we need to create the URL path for this view. There is nothing special needed for this, the parameter will automatically be appended to the url after we do a search. All we need to do is set up the url path for our view.

from django.contrib import admin
from django.urls import path
from .views import CreateVideo, DetailVideo, UpdateVideo, DeleteVideo, VideoCategoryList, SearchVideo
urlpatterns = [
path('search/', SearchVideo.as_view(), name='video-search'),
path('create/', CreateVideo.as_view(), name='video-create'),
path('<int:pk>/', DetailVideo.as_view(), name='video-detail'),
path('<int:pk>/update', UpdateVideo.as_view(), name='video-update'),
path('<int:pk>/delete', DeleteVideo.as_view(), name='video-delete'),
path('category/<int:pk>/', VideoCategoryList.as_view(), name='category-list'),
]

This is all that we will need to do to make this work, you should now be able to search the videos that we have posted to the site. That is where we are going to stop this tutorial at, we will come back later and add more to this application.

--

--