Skip to main content

Django Testimonials

PyPI version Build Status Documentation Status Coverage Status License: MIT

A high-performance, enterprise-grade Django package for managing customer testimonials at scale. Built with Django REST Framework and optimized for applications handling millions of testimonials with thousands of concurrent users.

🚀 Performance-First Design

  • ⚡ Sub-100ms API responses with intelligent caching
  • 📊 Optimized database queries with strategic indexing
  • 🔄 Background processing for emails and media
  • 📈 Horizontal scaling ready with background task support
  • 💾 Smart caching strategies with automatic invalidation

✨ Enterprise Features

Core Functionality

  • 📝 Complete testimonial management with approval workflows
  • ⭐ Flexible rating systems (1-10 scale, configurable)
  • 🏷️ Category organization with hierarchical support
  • 📎 Rich media attachments (images, videos, audio, documents)
  • 💬 Response system for official company replies
  • 👤 Anonymous testimonials with privacy controls

Performance & Scalability

  • 🚄 Smart caching for lightning-fast responses
  • ⚡ Background task processing with threading support
  • 🔍 Full-text search with optimized queries
  • 📊 Real-time statistics with cached aggregations
  • 🔄 Bulk operations for efficient moderation

Developer Experience

  • 🔌 Django REST Framework API with comprehensive endpoints
  • 📚 Extensive documentation with examples
  • 🧪 Comprehensive test suite with 95%+ coverage
  • 🌍 Internationalization ready with gettext support
  • 🔧 Highly configurable with 25+ settings

📋 Requirements

  • Python: 3.10+
  • Django: 4.2+
  • Django REST Framework: 3.14+
  • Pillow: 10.0+ (for image handling)
  • django-phonenumber-field: 7.0+
  • django-filter: 23.2+

Optional:

  • PostgreSQL (with psycopg): indexed full-text search that stays fast at millions of testimonials
  • Celery (pip install django-testimonials[celery]): if you already run Celery workers

🚀 Quick Start

1. Installation

pip install django-testimonials

2. Basic Configuration

Add to your INSTALLED_APPS:

INSTALLED_APPS = [
    # ... other apps
    'rest_framework',
    'django_filters',
    'testimonials',
]

3. Database Setup

python manage.py migrate testimonials

4. URL Configuration

# urls.py
from django.urls import path, include

urlpatterns = [
    # ... other patterns
    path('api/testimonials/', include('testimonials.api.urls')),
]

5. Basic Usage

from testimonials.models import Testimonial, TestimonialCategory

# Create a category
category = TestimonialCategory.objects.create(
    name="Product Reviews",
    description="Customer feedback on our products"
)

# Create a testimonial
testimonial = Testimonial.objects.create(
    author_name="John Doe",
    author_email="john@example.com",
    content="This product exceeded my expectations!",
    rating=5,
    category=category
)

# Get published testimonials (uses caching automatically)
testimonials = Testimonial.objects.published()
featured = Testimonial.objects.featured()

🔧 Performance Configuration

# settings.py
TESTIMONIALS_USE_CACHE = True
TESTIMONIALS_CACHE_TIMEOUT = 900  # 15 minutes

# Configure Django cache backend (Database Cache example)
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'testimonials_cache_table',
    }
}

Then run:

python manage.py createcachetable

Emails and thumbnails run through a task backend. The built-in database queue needs no extra infrastructure: tasks are stored in the same transaction as the testimonial, survive restarts and deploys, and are retried with backoff.

# settings.py
TESTIMONIALS_TASK_BACKEND = "database"   # or "celery", "thread", "sync", or a dotted path

Run one or more workers next to your web processes (under systemd, supervisor, or as a container):

python manage.py process_testimonial_tasks

Failed tasks are visible, and can be retried, in the Django admin under Testimonial Tasks. Notification emails are limited to TESTIMONIALS_EMAIL_RATE_LIMIT per minute; extra emails wait for the next minute instead of being dropped.

Email Notifications

# settings.py
TESTIMONIALS_NOTIFICATION_EMAIL = "admin@yoursite.com"

# Email backend configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-email@gmail.com'
EMAIL_HOST_PASSWORD = 'your-app-password'
DEFAULT_FROM_EMAIL = 'Your Site <noreply@yoursite.com>'

🏗️ Architecture Overview

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Frontend      │    │   Django API    │    │   Background    │
│   (React/Vue)   │◄──►│   (REST API)    │◄──►│   (Threads)     │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                              │                        │
                              ▼                        ▼
                    ┌─────────────────┐    ┌─────────────────┐
                    │   PostgreSQL    │    │  Django Cache    │
                    │   (Database)    │    │  (DB/LocMem)     │
                    └─────────────────┘    └─────────────────┘

📊 API Endpoints

Testimonials

  • GET /api/testimonials/ - List testimonials (cached)
  • POST /api/testimonials/ - Create testimonial
  • GET /api/testimonials/{id}/ - Get testimonial details
  • PUT/PATCH /api/testimonials/{id}/ - Update testimonial
  • DELETE /api/testimonials/{id}/ - Delete testimonial

Moderation (Admin/Moderator only)

  • POST /api/testimonials/{id}/approve/ - Approve testimonial
  • POST /api/testimonials/{id}/reject/ - Reject testimonial
  • POST /api/testimonials/{id}/feature/ - Feature testimonial
  • POST /api/testimonials/bulk_action/ - Bulk moderation

Categories

  • GET /api/categories/ - List categories (cached)
  • GET /api/categories/{id}/testimonials/ - Category testimonials

Media

  • GET /api/media/ - List media files
  • POST /api/testimonials/{id}/add_media/ - Add media to testimonial

Statistics & Analytics

  • GET /api/testimonials/stats/ - Get comprehensive statistics
  • GET /api/testimonials/featured/ - Get featured testimonials

💡 Usage Examples

Frontend Integration (JavaScript)

// Fetch testimonials with caching
const response = await fetch('/api/testimonials/?page=1&page_size=10');
const data = await response.json();

// Create a new testimonial
const testimonial = await fetch('/api/testimonials/', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRFToken': csrfToken
    },
    body: JSON.stringify({
        author_name: 'Jane Smith',
        content: 'Amazing service, highly recommend!',
        rating: 5,
        category_id: 1
    })
});

// Get featured testimonials (cached)
const featured = await fetch('/api/testimonials/featured/');

Django Templates

{% load static %}

<div class="testimonials-section">
    <h2>What Our Customers Say</h2>

    {% for testimonial in featured_testimonials %}
    <div class="testimonial-card">
        <div class="rating">
            {% for i in "12345"|make_list %}
                {% if forloop.counter <= testimonial.rating %}⭐{% endif %}
            {% endfor %}
        </div>

        <blockquote>{{ testimonial.content }}</blockquote>

        <cite>
            {{ testimonial.author_name }}
            {% if testimonial.company %}, {{ testimonial.company }}{% endif %}
        </cite>

        {% if testimonial.response %}
        <div class="company-response">
            <strong>Our Response:</strong> {{ testimonial.response }}
        </div>
        {% endif %}
    </div>
    {% endfor %}
</div>

Admin Bulk Operations

# In your admin or management command
from testimonials.models import Testimonial

# Approve multiple testimonials
testimonial_ids = [1, 2, 3, 4, 5]
testimonials = Testimonial.objects.filter(id__in=testimonial_ids)
for t in testimonials:
    t.approve(user=request.user)

🔒 Security Features

  • 🛡️ Permission-based access with role-based moderation
  • 🔐 CSRF protection for all API endpoints
  • 📝 Input validation with comprehensive sanitization
  • 🚫 Rate limiting for submissions (TESTIMONIALS_SUBMISSION_THROTTLE_RATE) and outgoing email
  • 👤 Anonymous submission with privacy controls: authors' contact details are never exposed publicly
  • 🖼️ Upload validation: real image checks, no SVG by default

🌍 Internationalization

# All user-facing strings support translation
from django.utils.translation import gettext_lazy as _

# Example usage in templates
{% load i18n %}
{% trans "Submit your testimonial" %}

# Configure languages in settings.py
LANGUAGES = [
    ('en', _('English')),
    ('es', _('Spanish')),
    ('fr', _('French')),
    # Add more languages
]

📈 Performance Benchmarks

Operation Without Optimization With Optimization Improvement
List API (100 items) 250ms 45ms 82% faster
Detail API 180ms 25ms 86% faster
Search queries 400ms 60ms 85% faster
Bulk approve (1000) 45 seconds 3 seconds 93% faster
Statistics calculation 800ms 50ms 94% faster

🎛️ Advanced Configuration

View all configuration options
# Performance & Caching
TESTIMONIALS_USE_CACHE = True
TESTIMONIALS_CACHE_TIMEOUT = 900
TESTIMONIALS_CACHE_KEY_PREFIX = "testimonials"

# Background Processing
TESTIMONIALS_USE_BACKGROUND_TASKS = True
TESTIMONIALS_EMAIL_RATE_LIMIT = 60

# File Handling
TESTIMONIALS_MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB
TESTIMONIALS_ENABLE_THUMBNAILS = True
TESTIMONIALS_THUMBNAIL_SIZES = {
    'small': (150, 150),
    'medium': (300, 300),
}

# Moderation
TESTIMONIALS_REQUIRE_APPROVAL = True
TESTIMONIALS_MODERATION_ROLES = ['content_manager']
TESTIMONIALS_ALLOW_ANONYMOUS = True

# Search & Pagination
TESTIMONIALS_SEARCH_MIN_LENGTH = 3
TESTIMONIALS_PAGINATION_SIZE = 10
TESTIMONIALS_SEARCH_RESULTS_LIMIT = 1000

# Features
TESTIMONIALS_ENABLE_CATEGORIES = True
TESTIMONIALS_ENABLE_MEDIA = True
TESTIMONIALS_ENABLE_DASHBOARD = True

🧪 Testing

# Run the full test suite
python -m pytest

# Run with coverage
python -m pytest --cov=testimonials --cov-report=html

# Run specific test categories
python -m pytest testimonials/tests/test_api_views.py
python -m pytest testimonials/tests/test_model.py
python -m pytest testimonials/tests/test_serializers.py

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📚 Documentation

Installation Guide https://github.com/NzeStan/django-testimonials/blob/main/docs/installation.md

Configuration Guide https://github.com/NzeStan/django-testimonials/blob/main/docs/configuration.md

API Reference https://github.com/NzeStan/django-testimonials/blob/main/docs/api.md

Performance Guide https://github.com/NzeStan/django-testimonials/blob/main/docs/performance.md

Deployment Guide https://github.com/NzeStan/django-testimonials/blob/main/docs/deployment.md

Customization Guide https://github.com/NzeStan/django-testimonials/blob/main/docs/customization.md

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

Built with Django – https://djangoproject.com/

Built with Django REST Framework – https://www.django-rest-framework.org/

Performance optimizations inspired by high-scale web applications

Icons and design elements from the open-source community

⭐ Support the Project

If this package helped you, please give it a star ⭐

Report Issues: https://github.com/NzeStan/django-testimonials/issues

Request Features / Discussions: https://github.com/NzeStan/django-testimonials/discussions

Documentation: https://django-testimonials.readthedocs.io/

Metadata

Release files for django-testimonials 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-testimonials 1.1.0
File Size Uploaded
django_testimonials-1.1.0.tar.gz 131.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-testimonials 1.1.0
File Interpreter ABI Platform
django_testimonials-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 255.4 kB

Release files / django_testimonials-1.1.0.tar.gz

Download URL django_testimonials-1.1.0.tar.gz
Size 131.0 kB
Tags Source
SHA-256 checksum
How to use checksums
efa576b414d516f3df20347a2efdb8a90091b9d090135fdf82ac1122f1a08ec4
BLAKE2b-256 checksum
How to use checksums
caf2b9cf59d55fa45fbed3405bd048b9c14ed51115582d7bc0eab595d4050cb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release files / django_testimonials-1.1.0-py3-none-any.whl

Download URL django_testimonials-1.1.0-py3-none-any.whl
Size 124.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c38150997dbba6ca2cf63f72a106c138ee375158654a323defa59abbe44bdcc4
BLAKE2b-256 checksum
How to use checksums
340d95cee08204fdd465cf802e581689dfa58a67eb437b8f147e5ccc77e4262d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.5

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page