Skip to content

Using Elasticsearch with Django and DRF

Elasticsearch can be used both in REST APIs and directly within Django applications. It is not limited to just one type of usage.

Here's a breakdown of how Elasticsearch can be integrated and used in different contexts:

  1. Direct Integration in Django:

    • Model Indexing:

      Index Django models directly into Elasticsearch. This can be done using libraries like django-elasticsearch-dsl, which provides Django-friendly abstractions to define Elasticsearch indices and documents that map to Django models.

    • Search Views:

      Create search views in Django to handle search queries and display results. This allows you to build powerful search features into your Django web application.

    • Template Rendering:

      Use Django templates to render search results directly on web pages, enabling full-text search capabilities in your Django web application.

  2. Using Elasticsearch in Django REST Framework (DRF):

    • API Endpoints:

      Create REST API endpoints that utilize Elasticsearch for searching and retrieving data. This is particularly useful for building search APIs that can be consumed by various clients, including web and mobile applications.

    • Serializers:

      Serialize Elasticsearch search results into JSON format, which can be returned by API endpoints.

    • DRF Integration:

      Integrate Elasticsearch with Django REST Framework views and viewsets, enabling advanced search capabilities within your REST API.


Example: Direct Integration in Django

Here’s a simple example of how to integrate Elasticsearch directly within a Django application, as covered earlier:

  1. Install Dependencies

    bash

    pip install elasticsearch-dsl django-elasticsearch-dsl
    
  2. Configure Elasticsearch in Django Settings

    settings.py

    ELASTICSEARCH_DSL = {
        'default': {
            'hosts': 'localhost:9200'
        },
    }
    
  3. Define Django Model and Elasticsearch Document

    models.py

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=255)
        author = models.CharField(max_length=255)
        published_date = models.DateField()
        summary = models.TextField()
    
        def __str__(self):
            return self.title
    

    documents.py

    from django_elasticsearch_dsl import Document
    from django_elasticsearch_dsl.registries import registry
    from .models import Book
    
    @registry.register_document
    class BookDocument(Document):
        class Index:
            name = 'books'
    
        class Django:
            model = Book
            fields = [
                'title',
                'author',
                'published_date',
                'summary',
            ]
    
  4. Create Search View

    views.py

    from django.shortcuts import render
    from .documents import BookDocument
    
    def search(request):
        query = request.GET.get('q')
        if query:
            books = BookDocument.search().query("multi_match", query=query, fields=['title', 'author', 'summary'])
        else:
            books = BookDocument.search()
    
        return render(request, 'search_results.html', {'books': books})
    
  5. Define URL Pattern

    urls.py

    from django.urls import path
    from .views import search
    
    urlpatterns = [
        path('search/', search, name='search'),
    ]
    
  6. Create Template

    templates/search_results.html

    <!DOCTYPE html>
    <html>
    <head>
        <title>Search Results</title>
    </head>
    <body>
        <h1>Search Results</h1>
        <form method="GET" action="{% url 'search' %}">
            <input type="text" name="q" placeholder="Search for books..." value="{{ request.GET.q }}">
            <button type="submit">Search</button>
        </form>
        <ul>
            {% for book in books %}
                <li>{{ book.title }} by {{ book.author }} ({{ book.published_date }})</li>
            {% empty %}
                <li>No results found.</li>
            {% endfor %}
        </ul>
    </body>
    </html>
    

Example: Using Elasticsearch in Django REST Framework

  1. Install Dependencies

    bash

    pip install djangorestframework elasticsearch-dsl django-elasticsearch-dsl
    
  2. Create API View

    api_views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from .documents import BookDocument
    
    class BookSearchAPIView(APIView):
        def get(self, request):
            query = request.GET.get('q')
            if query:
                books = BookDocument.search().query("multi_match", query=query, fields=['title', 'author', 'summary'])
            else:
                books = BookDocument.search()
    
            results = [{'title': book.title, 'author': book.author, 'published_date': book.published_date, 'summary': book.summary} for book in books]
            return Response(results)
    
  3. Define URL Pattern for API

    urls.py

    from django.urls import path
    from .api_views import BookSearchAPIView
    
    urlpatterns = [
        path('api/search/', BookSearchAPIView.as_view(), name='api_search'),
    ]
    

Conclusion

Elasticsearch can be used in both traditional Django views and in Django REST Framework to provide advanced search capabilities. The integration allows for powerful full-text search features that are not limited to just REST APIs but can also enhance the search functionality of a Django web application directly. This flexibility makes Elasticsearch a valuable tool for a wide range of use cases in Django projects.