Danny Brown

A Blog on Code and Occasionally Other Things

Implementing Search Functionality into a Django Site

Danny BrownJanuary 5, 2019

I’ve decided to add search functionality to my website TallyMusic.net. The site tracks local and touring acts coming through Tallahassee, and I think it will be more useful for finding particular things by being able to search the site.

urls.py
import concerts.views as concert_views
urlpatterns = [
    ...
    url(r'^search/$', concert_views.search, name="search")
]

The search function will be searching thorugh my concerts app, so that’s where I’ll be writing my view. I could have put it in my concerts app’s urls.py file, but it seemed right to me to put it in the project urls.py file, since it will be used across the site. I’d be happy to entertain other theories on this.

concerts/views.py
def search(request):
    if request.method == 'GET':
        search_term = request.GET.get('search')
        try:
            headliners = Concert.objects.filter(headliner__search=search_term)
            notes = Concert.objects.filter(notes__search=search_term)
            support = Concert.objects.filter(support__search=search_term)
            venues = Concert.objects.filter(venue__name__search=search_term)
            prices = Concert.objects.filter(price__search=search_term)
            ages = Concert.objects.filter(age__search=search_term)
            results = headliners | notes | support | venues | prices | ages
        except Concert.DoesNotExist:
            results = None
        template = "concerts/search.html"
        context = {"results" : results, "search_term" : search_term}
        return render(request, template, context)
    else:
        return render(request, template, {})

Here we’re taking the user’s search term using request.GET.get('search'), then searching several fields of the model for possible matches (seen in the try clause). After that, we simply return a render() of the results.

concerts/search.html
{% extends 'base.html' %}

{% block content %}

<h1>Search for: {{ search_term }}</h1>
<p>Found {{ results|length }} result{{ results|pluralize }}.</p>

<div class="concerts">
{% if results %}
  {% for result in results %}
  <div class="concert">
    <div class="date">
      <span class="day">{{ result.date.day }}</span>
      <span class="month">{{ result.date|date:'F' }}</span>
      <span class="year">{{ result.date.year }}</span>
    </div>
    <div class="details">
      <div class="bg-image"></div>
      <span class="headliner">{{ result.headliner }}</span>
      <span class="support">{{ result.support }}</span>
      <span class="price">{{ result.price }}</span>
      {% if result.notes %}
      <div class="notes open">Click for more information &#8595;</div>
      <div class="notes">{{ result.notes|linebreaksbr }}</div>
      <div class="notes">Click to hide &#8593;</div>
      {% endif %}
      <span class="concert_website">
        <a href="{{ result.website }}" target="_blank">
          Event Website &#9835;
        </a>
      </span>
    </div>
    <div class="venue">
      <span class="venue_name">
        <a href="{% url 'concerts:venue_events' slug=result.venue.slug %}">
          {{ result.venue.name }}
        </a>
      </span>
      <span class="address">
        <a href="https://www.google.com/maps?q={{ result.venue.address }}"
           target="_blank">
          {{ result.venue.address }}
        </a>
      </span>
      <span class="venue_website">
        <a href="{{ result.venue.website }}" target="_blank">
          Venue Website &#9833;
        </a>
      </span>
    </div>
  </div>
  {% endfor %}
{% endif %}
</div>

{% endblock %}

I borrowed heavily from my main page HTML here. There’s a lot going on here, but basically it just renders all the fields in the model the way I want. The header section shows the search term and number of results.

settings.py
INSTALLED_APPS = [
    ...
    'django.contrib.postgres',

One more thing! I used PostgreSQL’s full text search engine in my views.py file. If I don’t add it to my installed apps, my site will throw an error.

CSS is beyond the scope of this post, but after lots of CSS wizardry, I’ve got desktop, tablet, and mobile versions of the search bar up and running:

And some sample search results for good measure:

There it is!

 

Posted In code | Django | HTML | Python

Post navigation

PreviousPopulating Merge Fields in a Word Document Using Python
NextA 2018 of Live Music in Review

Danny Brown

A Dev Blog with Some Tangents

About

Categories

  • code
    • APIs
    • Bash
    • CSS
    • Django
    • HTML
    • JavaScript
    • Python
    • S3
    • Selenium
    • Serverless
    • TypeScript
  • games
  • music
    • concert reviews
    • synthesizers
  • opinion
  • sports
  • tech
    • Bitbucket
    • Git
    • GitHub
    • MS Teams
    • WordPress
  • theater

Recent Posts

  • Open Pull Requests from the Terminal (One of My Favorite Dotfiles Scripts)
  • Dotfiles Script for a New TypeScript/Node Project
  • So I Told You to Go See a Broadway Play? Tips for Theater in New York
  • Build a Simple Microsoft Teams Bot Easily, No SDK Required
  • Creating a GUI for Conway’s Game of Life Using Pygame and Numpy

External Links

  • GitHub
  • LinkedIn

Recent Posts

  • Open Pull Requests from the Terminal (One of My Favorite Dotfiles Scripts)
  • Dotfiles Script for a New TypeScript/Node Project
  • So I Told You to Go See a Broadway Play? Tips for Theater in New York
  • Build a Simple Microsoft Teams Bot Easily, No SDK Required
  • Creating a GUI for Conway’s Game of Life Using Pygame and Numpy

Categories

  • code
    • APIs
    • Bash
    • CSS
    • Django
    • HTML
    • JavaScript
    • Python
    • S3
    • Selenium
    • Serverless
    • TypeScript
  • games
  • music
    • concert reviews
    • synthesizers
  • opinion
  • sports
  • tech
    • Bitbucket
    • Git
    • GitHub
    • MS Teams
    • WordPress
  • theater
Copyright © 2025. Danny Brown
Powered By WordPress and Meritorious