Django Testimonials
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
Caching (Recommended)
# 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
Durable Background Tasks (Recommended for production)
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 testimonialGET /api/testimonials/{id}/- Get testimonial detailsPUT/PATCH /api/testimonials/{id}/- Update testimonialDELETE /api/testimonials/{id}/- Delete testimonial
Moderation (Admin/Moderator only)
POST /api/testimonials/{id}/approve/- Approve testimonialPOST /api/testimonials/{id}/reject/- Reject testimonialPOST /api/testimonials/{id}/feature/- Feature testimonialPOST /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 filesPOST /api/testimonials/{id}/add_media/- Add media to testimonial
Statistics & Analytics
GET /api/testimonials/stats/- Get comprehensive statisticsGET /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.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - 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)
| File | Size | Uploaded | |
|---|---|---|---|
| django_testimonials-1.1.0.tar.gz | 131.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|