Skip to main content

Official ParadeDB integration for Django

Project description

django-paradedb

PyPI Codecov CI License Slack URL X URL

ParadeDB — simple, Elastic-quality search for Postgres — integration for Django ORM.

Requirements & Compatibility

Component Supported
Python 3.10+
Django 4.2+
ParadeDB 0.21.0+
PostgreSQL 17+ (with ParadeDB extension)

Installation

pip install django-paradedb

Quick Start

Add a BM25 index to your model and use ParadeDBManager:

from django.db import models
from paradedb.indexes import BM25Index
from paradedb.queryset import ParadeDBManager

class Product(models.Model):
    description = models.TextField()
    category = models.CharField(max_length=100)
    rating = models.IntegerField(default=0)

    objects = ParadeDBManager()

    class Meta:
        indexes = [
            BM25Index(
                fields={
                    'id': {},
                    'description': {'tokenizer': 'unicode_words'},
                    'category': {'tokenizer': 'literal'},
                    'rating': {},
                },
                key_field='id',
                name='product_search_idx',
            ),
        ]

Run migrations to create the index:

python manage.py makemigrations
python manage.py migrate

Search with a simple query:

from paradedb.search import ParadeDB, Fuzzy

# Single term
Product.objects.filter(description=ParadeDB('shoes'))

# Multiple terms (AND by default)
Product.objects.filter(description=ParadeDB('running', 'shoes'))

# OR across terms
Product.objects.filter(description=ParadeDB('shoes', 'boots', operator='OR'))

# Fuzzy search (typo tolerance)
Product.objects.filter(description=ParadeDB(Fuzzy('shoez')))

Annotate with BM25 relevance score and sort by it:

from paradedb.functions import Score

Product.objects.filter(
    description=ParadeDB('shoes')
).annotate(
    score=Score()
).order_by('-score')

Django ORM Integration

django-paradedb works seamlessly with Django's ORM features:

from django.db.models import Q
from paradedb.search import ParadeDB

# Combine with Q objects
Product.objects.filter(
    Q(description=ParadeDB('shoes')) & Q(rating__gte=4)
)

# Chain with standard filters
Product.objects.filter(
    description=ParadeDB('shoes')
).filter(
    category='footwear'
).exclude(
    rating__lt=3
)

# Select related
Product.objects.filter(
    description=ParadeDB('shoes')
).select_related('brand')

# Prefetch related
Product.objects.filter(
    description=ParadeDB('shoes')
).prefetch_related('reviews')

Custom Manager

If you have a custom manager, compose it with ParadeDBQuerySet:

from paradedb.queryset import ParadeDBQuerySet

class CustomManager(models.Manager):
    def active(self):
        return self.filter(is_active=True)

CustomManagerWithParadeDB = CustomManager.from_queryset(ParadeDBQuerySet)

class Product(models.Model):
    objects = CustomManagerWithParadeDB()

Common Errors

"facets() requires a ParadeDB operator in the WHERE clause"

# ❌ Missing ParadeDB filter
Product.objects.filter(price__lt=100).order_by('id')[:10].facets('category')

# ✅ Add a ParadeDB search filter
Product.objects.filter(
    price__lt=100,
    description=ParadeDB('shoes')
).order_by('id')[:10].facets('category')

"facets(include_rows=True) requires order_by() and a LIMIT"

# ❌ Missing ordering or limit
Product.objects.filter(description=ParadeDB('shoes'))[:10].facets('category')
Product.objects.filter(description=ParadeDB('shoes')).order_by('id').facets('category')

# ✅ Both ordering and limit
Product.objects.filter(description=ParadeDB('shoes')).order_by('id')[:10].facets('category')

# ✅ Or skip rows entirely
Product.objects.filter(description=ParadeDB('shoes')).facets('category', include_rows=False)

Security

django-paradedb uses SQL literal escaping (rather than parameterized queries) for search terms. This is intentional: ParadeDB's full-text operators (&&&, |||, ===, @@@, etc.) require string literals that the query planner can inspect at parse time — parameterized placeholders are incompatible with this design. All user input is escaped via PostgreSQL's standard single-quote escaping (''') before being embedded in the query. The implementation is covered by 300+ tests including special-character and injection cases. MoreLikeThis and standard Django filters continue to use normal parameterization.

Examples

Documentation

Contributing

See CONTRIBUTING.md for development setup, running tests, linting, and the PR workflow.

Support

If you're missing a feature or have found a bug, please open a GitHub Issue.

To get community support, you can:

If you need commercial support, please contact the ParadeDB team.

Acknowledgments

We would like to thank the following members of the Django community for their valuable feedback and reviews during the development of this package:

  • Timothy Allen - Principal Engineer at The Wharton School, PSF and DSF member
  • Frank Wiles - President & Founder of REVSYS

License

django-paradedb is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_paradedb-0.3.0.tar.gz (157.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_paradedb-0.3.0-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file django_paradedb-0.3.0.tar.gz.

File metadata

  • Download URL: django_paradedb-0.3.0.tar.gz
  • Upload date:
  • Size: 157.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for django_paradedb-0.3.0.tar.gz
Algorithm Hash digest
SHA256 47a229eec082576060e78934fc75abbaf889df18ee72369da02ab7436c276d9a
MD5 1a3e8406cb067aa3e2364253e38433fc
BLAKE2b-256 06b8f533b68c8d7153023c345df3233eb5c72f1f56f0e40e3508e7dd0973f4c6

See more details on using hashes here.

File details

Details for the file django_paradedb-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_paradedb-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01b8dbd338d68ebcd1b51d07111219e75aa1566c9cef3d36a19cfa6160504f88
MD5 fb3156269dfa1daa846e9a76a51a30e0
BLAKE2b-256 7e339e05b86e28b6d9fa70f841cb3cef839ade318ce1461f2e0c84664798e67b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page