So after about 2 years after I am writing this blog post.
What can I do?
I am very lazy...
After procrastinating for 2 years I've decided to finally write a blog post
I assume that you have some basic knowledge of Django requests and responses, like GET and POST request and URL mapping etc.
So, let's get to the point.
For example we have a model called Book
# models.py
from django.db import models
class Book(models.Model):
"""
A Simple Book Model
"""
ISBN_HELP_URL = "https://www.isbn-
international.org/content/what-isbn"
name = models.CharField(max_length=255)
author = models.CharField(max_length=255)
summary = models.TextField(blank=True, null=True)
isbn = models.CharField(help_text=f"<a href='{ISBN_HELP_URL}'
target='_blank'>More Info</a>", max_length=10)
genre = models.CharField(max_length=255, help_text="Enter a
book genre (e.g. Science Fiction, French Poetry etc.)")
def __str__(self):
return self.name
So we want to make a page to search for a Book
based on the following fields:
- name
- author
- summary
- isbn
- genre
We can simply use the Q
operator.
It is built in to Django.
It is used to Join the querysets.
Here is a simple example:
# views.py
from django.db.models import Q
from django.shortcuts import render, redirect
from .models import Book
def frontpage(request):
"""
The default frontpage
Return all the books in the database.
"""
books = Book.objects.all()
return render(request, "frontpage.html", {"books": books})
def search(request):
"""
Searches the books based on the query.
"""
query = request.GET.get("query", None)
if query:
books = Book.objects.filter(
Q(name__icontains=query) |
Q(author__icontains=query) |
Q(summary__icontains=query) |
Q(isbn__icontains=query) |
Q(genre__icontains=query)
)
return render(request, "search.html", {"books": books})
return redirect(request, "frontpage")
Now that looks so complicated, but it isn't
If you understand what this code is doing you can easily implement in your projects
So let's break this down into pieces.
The function
frontpage
, well shows the frontpage with all the Books in the database, easy.The
search
function searches the books based on the query entered by the user.
The query can match the name, author, summary, ISBN, or genre of the book.
If a query is entered, the function filters the books and returns the filtered books to be displayed in the "search.html" template.
If no query is entered, the function redirects the user to the "frontpage".
We are firstly importing the Q
operator from django.db.models
.
Then we are filtering the Books based on the fields
This is the main code
books = Book.objects.filter(
Q(name__icontains=query) |
Q(author__icontains=query) |
Q(summary__icontains=query) |
Q(isbn__icontains=query) |
Q(genre__icontains=query)
)
The |
indicate that we are joining the queryset so even if the query isn't matched with the name but matched with the author it will fetch that book from the database
This double underscores and icontains represent that we also want to make the query case insensitive.
For example if we want to search for a Book named The Brief History of Time by Stephen Hawking,
We don't have to type the exact name of the book.
The Query could include the following:
- the brief history of time
- THE BRIEF HISTORY OF TIME
- History of Time
- brief history
The possibilities could get endless.
So now let's map the views to the urls
Open the urls.py
# urls.py
from django.contrib import admin
from django.urls import path
from myapp import views
urlpatterns = [
path('', views.frontpage, name="frontpage"),
path('/search/', views.search, name="search"),
path('admin/', admin.site.urls),
]
Now let's move to the frontend
Create a folder in myapp
(Your app folder) named as templates
.
In it create two files named:
frontpage.html
search.html
If you wish you can use a base.html and template inheritance, but here I will be doing the simple html with no css, so it will look ugly.
<!-- frontpage.html -->
<html>
<head>
<title>Jamshedpur Library</title
</head>
<body>
<h2>Jamshedpur Library</h2>
<p>Frontpage</p>
<form action="{% url 'search' %}" method="GET">
<input type="search" placeholder="search" name="query">
<button type="submit">Search 🔍</button>
</form>
<ul>
{% for book in books %}
<li>{{ book.name }} by {{ book.author }}</li>
{% endfor %}
</ul>
</body>
</html>
Yup it's a form which will send get request to search
view, remember we have added a name attribute in the url patterns
Now let's see the search.html
<!-- search.html -->
<html>
<head>
<title>Jamshedpur Library</title
</head>
<body>
<h2>Jamshedpur Library</h2>
<form action="{% url 'search' %}" method="GET">
<input type="search" placeholder="search" name="query">
<button type="submit">Search 🔍</button>
</form>
<p>You have searched for: {{ request.GET.query }}</p>
<p>Results: {{ books.count }}</p>
<ul>
{% for book in books %}
<li>{{ book.name }} by {{ book.author }}</li>
{% endfor %}
</ul>
</body>
</html>
So here we are displaying the search results with the no. of results just as in any search engine.
BTW I have not implemented the pagination, so the data isn't spliced into smaller chunks
Well that's how you can implement a simple search in your Django project.
Also, the letter Capital G
looks like an arrow going in a circle.
Thanks for reading my post.
@foxy4096 out.
Cheers ✌
Top comments (1)
I am tired.