A powerful, production-ready crowdfunding REST API built with Django & Django REST Framework
- Overview
- Features
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- API Reference
- Authentication Flow
- Data Models
- Deployment
Fundly is a full-featured crowdfunding platform backend that allows users to create projects, receive donations, engage with comments, and rate campaigns. It is built for scale, with clean architecture, JWT-based authentication, email verification, and optional Cloudinary media hosting.
| Feature | Description |
|---|---|
| 🔐 Auth & Security | JWT access/refresh tokens, token blacklisting, email verification |
| 👤 User Management | Custom user model with email-based auth, profile management, password reset |
| 📁 Projects | Full CRUD, categories, tags, image uploads, featured & top-rated listings |
| 💰 Donations | Per-project donations with live progress tracking |
| 💬 Comments | Nested comments (1-level deep replies) with author info |
| ⭐ Ratings | 1–5 star project ratings with average aggregation |
| 🚩 Reports | Flag projects or comments for spam/inappropriate content |
| 🔍 Search & Filter | Full-text search, category/tag filtering, ordering |
| Transactional emails via SendGrid (activation & password reset) | |
| ☁️ Media | Local filesystem or Cloudinary (toggle via env var) |
| 🌐 CORS | Configured for React/Vite frontends |
- Framework: Django 6.0 + Django REST Framework 3.17
- Database: PostgreSQL (via
psycopg2-binary) - Auth:
djangorestframework-simplejwtwith token blacklisting - Email:
django-anymail+ SendGrid - Media: Pillow + optional
django-cloudinary-storage - Static Files: WhiteNoise
- Filtering:
django-filter - Config:
python-decouple - Deployment: Gunicorn + Render-ready
Fundly-Backend/
│
├── config/ # Django project settings & routing
│ ├── settings.py # All settings (env-driven)
│ ├── urls.py # Root URL configuration
│ ├── wsgi.py
│ └── asgi.py
│
├── accounts/ # Custom user model & auth
│ ├── models.py # CustomUser (email-based)
│ ├── serializers.py # Register, login, profile, password
│ ├── views.py # Auth endpoints
│ ├── urls.py
│ └── utils.py # Email sending helpers
│
├── projects/ # Crowdfunding projects
│ ├── models.py # Project, Category, Tag, ProjectImage
│ ├── serializers.py # List, detail, write serializers
│ ├── views.py # CRUD + featured/top-rated/similar
│ ├── filters.py
│ └── permissions.py
│
├── donations/ # Donation handling
│ ├── models.py # Donation model
│ ├── serializers.py
│ └── views.py
│
├── comments/ # Project comments & replies
│ ├── models.py # Comment (self-referencing for replies)
│ ├── serializers.py
│ └── views.py
│
├── ratings/ # Project star ratings
│ ├── models.py # Rating (1–5, one per user per project)
│ ├── serializers.py
│ └── views.py
│
├── reports/ # Flagging content
│ ├── models.py # Report (project or comment)
│ ├── serializers.py
│ └── views.py
│
├── manage.py
└── requirements.txt
- Python 3.12+
- PostgreSQL 14+
- (Optional) A Cloudinary account for media hosting
- (Optional) A SendGrid API key for emails
git clone https://github.com/your-org/fundly-backend.git
cd fundly-backendpython -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windowspip install -r requirements.txtcp .env.example .env
# Edit .env with your values — see Environment Variables belowpsql -U postgres -c "CREATE DATABASE crowdfunding_db;"python manage.py migratepython manage.py createsuperuserpython manage.py runserverThe API will be available at http://localhost:8000.
Create a .env file in the project root based on .env.example:
# Django
SECRET_KEY=your-secret-key-here
DEBUG=True
# Database
DB_NAME=crowdfunding_db
DB_USER=postgres
DB_PASSWORD=your-db-password
DB_HOST=localhost
DB_PORT=5432
# Email (SendGrid)
SENDGRID_API_KEY=your-sendgrid-api-key
DEFAULT_FROM_EMAIL=hello@yourapp.com
# Frontend (used in activation & reset email links)
FRONTEND_URL_DEPLOY=http://localhost:5173
# Media Storage (set to True to use Cloudinary)
USE_CLOUDINARY=False
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secretBase URL: /api/
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/register/ |
❌ | Register a new user |
GET |
/auth/activate/<uid>/<token>/ |
❌ | Verify email address |
POST |
/auth/login/ |
❌ | Login & receive JWT tokens |
POST |
/auth/logout/ |
✅ | Logout & blacklist refresh token |
POST |
/auth/token/refresh/ |
❌ | Refresh access token |
GET/PATCH |
/auth/profile/ |
✅ | View or update profile |
DELETE |
/auth/profile/delete/ |
✅ | Delete account |
POST |
/auth/password/change/ |
✅ | Change password |
POST |
/auth/password/reset/ |
❌ | Request password reset email |
POST |
/auth/password/reset/confirm/<uid>/<token>/ |
❌ | Set new password |
GET |
/auth/users/ |
🔑 Admin | List all users |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/projects/ |
❌ | List all projects (filter, search, paginate) |
POST |
/projects/ |
✅ | Create a new project |
GET |
/projects/<id>/ |
❌ | Retrieve project details |
PUT/PATCH |
/projects/<id>/ |
✅ Owner | Update project |
POST |
/projects/<id>/cancel/ |
✅ Owner | Cancel project (if progress < 25%) |
GET |
/projects/<id>/similar/ |
❌ | Get similar projects by tags |
GET |
/projects/featured/ |
❌ | List featured projects |
GET |
/projects/top-rated/ |
❌ | List top-rated active projects |
GET |
/projects/categories/ |
❌ | List all categories |
POST |
/projects/categories/ |
🔑 Admin | Create a category |
GET |
/projects/tags/ |
❌ | List all tags |
POST |
/projects/tags/ |
🔑 Admin | Create a tag |
Query Parameters for GET /projects/:
?search=keyword # Search title, description, tags
?category=slug # Filter by category slug
?tag=slug # Filter by tag slug
?owner=user_id # Filter by owner
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/donations/donate/<project_id>/ |
✅ | Make a donation |
GET |
/donations/project/<project_id>/ |
❌ | Get project donation details |
GET |
/donations/my-donations/ |
✅ | Get current user's donation history |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/comments/project/<project_id>/ |
❌ | List comments for a project |
POST |
/comments/project/<project_id>/ |
✅ | Post a comment |
POST |
/comments/<comment_id>/reply/ |
✅ | Reply to a comment |
PATCH |
/comments/<comment_id>/ |
✅ Owner | Edit a comment |
DELETE |
/comments/<comment_id>/ |
✅ Owner | Delete a comment |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/ratings/create/ |
✅ | Rate a project (1–5 stars) |
GET |
/ratings/project/<project_id>/ |
❌ | Get rating stats for a project |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/reports/create/ |
✅ | Report a project or comment |
GET |
/reports/reasons/ |
❌ | List available report reason choices |
1. POST /api/auth/register/ → Creates user (is_email_verified=False)
2. Email sent with activation link
3. GET /api/auth/activate/<uid>/<token>/ → Verifies email
4. POST /api/auth/login/ → Returns { access, refresh }
5. Include header: Authorization: Bearer <access_token>
6. POST /api/auth/token/refresh/ → Get new access token
7. POST /api/auth/logout/ → Blacklists refresh token
email (unique, indexed) | first_name | last_name | phone
profile_picture | date_of_birth | country | bio
is_email_verified | created_at | updated_at
owner (FK→User) | title | description | target (decimal)
category (FK→Category) | tags (M2M→Tag) | start_time | end_time
status [active|cancelled|completed] | is_featured
→ computed: progress (%), avg_rating
user (FK→User) | project (FK→Project) | amount | created_at
project (FK→Project) | user (FK→User) | parent (FK→self, nullable)
content | created_at | updated_at
user (FK→User) | project (FK→Project) | value (1–5)
unique_together: (user, project)
user (FK→User) | project (FK→Project, nullable) | comment (FK→Comment, nullable)
reason [spam|inappropriate|offensive|other] | created_at
This project is configured for deployment on Render.
- Push your code to GitHub.
- Create a Web Service on Render pointing to your repo.
- Set Build Command:
pip install -r requirements.txt && python manage.py migrate && python manage.py collectstatic --noinput
- Set Start Command:
gunicorn config.wsgi:application
- Add all required Environment Variables in the Render dashboard.
-
DEBUG=False -
SECRET_KEYis long, random, and secret -
ALLOWED_HOSTSincludes your Render domain - PostgreSQL add-on configured in Render
-
USE_CLOUDINARY=Truewith valid credentials (recommended for media) -
SENDGRID_API_KEYset for transactional emails -
FRONTEND_URL_DEPLOYpoints to your deployed frontend
Pull requests are welcome! For major changes, please open an issue first to discuss what you'd like to change.
- Fork the repository
- Create your feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m 'Add my feature' - Push to the branch:
git push origin feature/my-feature - Open a pull request
| Avatar | Name | GitHub |
|---|---|---|
![]() |
Ebrahim Mostafa | @ebrahimmostafa133 |
![]() |
Mostafa Khalifa | @Mostafa-Khalifaa |
![]() |
Shahd | @Shahd3711 |
![]() |
Khaled | @Khaleddd11 |
![]() |
Ahmed Ehab | @ahmed-ehab-reffat |
Made with ❤️ by the Fundly Team




