Quick Start

1. Add to INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    # Django Unfold (must be before django.contrib.admin)
    "unfold",
    "unfold.contrib.filters",
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",

    # Third-party
    "rest_framework",
    "django_celery_beat",

    # Subscription package
    "subscriptions",
]

2. Environment Variables

Create a .env file:

# Django
DJANGO_SECRET_KEY=
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=*,localhost,127.0.0.1

# Celery / Redis
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/0

# Midtrans (get from https://dashboard.midtrans.com)
MIDTRANS_SERVER_KEY=
MIDTRANS_CLIENT_KEY=
MIDTRANS_MERCHANT_ID=
MIDTRANS_IS_PRODUCTION=False
MIDTRANS_NOTIFICATION_URL=

Important

All credential values must be empty by default. Fill them with your own Midtrans sandbox credentials during development.

3. Configure Django Settings

# settings.py
from decouple import config

# Midtrans Configuration
MIDTRANS_SERVER_KEY = config("MIDTRANS_SERVER_KEY", default="")
MIDTRANS_CLIENT_KEY = config("MIDTRANS_CLIENT_KEY", default="")
MIDTRANS_MERCHANT_ID = config("MIDTRANS_MERCHANT_ID", default="")
MIDTRANS_IS_PRODUCTION = config("MIDTRANS_IS_PRODUCTION", default=False, cast=bool)
MIDTRANS_API_BASE_URL = (
    "https://api.midtrans.com" if MIDTRANS_IS_PRODUCTION
    else "https://api.sandbox.midtrans.com"
)
MIDTRANS_NOTIFICATION_URL = config("MIDTRANS_NOTIFICATION_URL", default="")

# Celery
CELERY_BROKER_URL = config("CELERY_BROKER_URL", default="redis://localhost:6379/0")
CELERY_RESULT_BACKEND = config("CELERY_RESULT_BACKEND", default="redis://localhost:6379/0")
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"

# REST Framework
REST_FRAMEWORK = {
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 20,
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.BasicAuthentication",
    ],
}

# Subscription Settings (optional overrides)
SUBSCRIPTION_SETTINGS = {
    "PROTECTED_PATHS": [],
    "SUBSCRIPTION_REQUIRED_REDIRECT": "/pricing/",
    "GRACE_PERIOD_DAYS": 3,
    "PAYMENT_EXPIRY_MINUTES": 60,
    "AUTO_GENERATE_INVOICE": True,
    "AUTO_RETRY_FAILED_PAYMENTS": True,
    "MAX_RETRY_ATTEMPTS": 3,
    "RETRY_INTERVAL_DAYS": 1,
    "INVOICE_NUMBER_PREFIX": "INV",
    "SEND_EMAIL_NOTIFICATIONS": True,
    "EXPIRY_REMINDER_DAYS": [7, 3, 1],
}

4. Celery Configuration

# config/celery.py
import os
from celery import Celery

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

app = Celery("config")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()
# config/__init__.py
from .celery import app as celery_app

__all__ = ["celery_app"]

5. URL Configuration

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

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/subscriptions/", include("subscriptions.urls")),
]

6. Run Migrations & Setup

python manage.py migrate
python manage.py setup_periodic_tasks
python manage.py seed_plans          # Optional: create sample plans
python manage.py createsuperuser

7. Start Services

# Terminal 1: Redis
redis-server

# Terminal 2: Django
python manage.py runserver

# Terminal 3: Celery Worker
celery -A config worker -l info

# Terminal 4: Celery Beat
celery -A config beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

Next Steps