Skip to main content

Reusable Django planner app — tasks, calendar events, reminders with GenericFK linking, Celery reminders, and optional FCM push.

Project description

nai-planner

Reusable Django planner — tasks, calendar events, and reminders with GenericFK linking, Celery-powered reminders, and optional FCM push notifications.

Architecture

Single model (PlannerItem) handles three item types:

Type Purpose Key Fields
task To-do items with deadlines due_at, priority, is_completed
event Calendar events with duration due_at, end_at, is_all_day
reminder Time-triggered notifications remind_at, is_reminder_sent

GenericFK — any item can link to any Django model (Note, Chat, Project, etc.) via content_type + object_id.

Soft delete — items are never hard-deleted. deleted_at timestamp hides them from default queries. Restore anytime.

ManagersPlannerItem.objects excludes soft-deleted items. PlannerItem.all_objects includes everything.

Install

# Core only (models + signals + admin)
pip install nai-planner

# With Django REST Framework support
pip install nai-planner[drf]

# With Django Ninja support
pip install nai-planner[ninja]

# With FCM push notifications
pip install nai-planner[fcm]

# With Celery periodic tasks
pip install nai-planner[celery]

# Everything
pip install nai-planner[all]

Quick Start

1. Add to INSTALLED_APPS

INSTALLED_APPS = [
    # ...
    "nai_planner",
]

2. Run migrations

python manage.py migrate nai_planner

3. Wire up URLs

DRF:

from nai_planner.contrib.drf.urls import urlpatterns as planner_urls

urlpatterns = [
    path("api/v1/", include(planner_urls)),
]

Django Ninja:

from nai_planner.contrib.ninja.views import router as planner_router

api.add_router("/planner", planner_router)

4. Setup Celery Beat (optional)

python manage.py setup_planner_beat

5. Configure FCM (optional)

# settings.py
NAI_PLANNER_FCM_ENABLED = True
NAI_PLANNER_FCM_CREDENTIALS_PATH = "/path/to/firebase-credentials.json"
NAI_PLANNER_FCM_TOKEN_GETTER = "myapp.utils.get_user_fcm_tokens"

The FCM_TOKEN_GETTER must be a dotted path to a callable: callable(user) -> list[str]

API Endpoints

DRF (ViewSet at /api/v1/planner/)

Method Endpoint Description
GET /planner/ List user's items (filterable)
POST /planner/ Create item
GET /planner/{uuid}/ Get item detail
PUT/PATCH /planner/{uuid}/ Update item
DELETE /planner/{uuid}/ Soft delete item
POST /planner/{uuid}/complete/ Mark as completed
POST /planner/{uuid}/restore/ Restore soft-deleted item

Filters: ?item_type=task, ?priority=high, ?is_completed=true, ?due_after=2025-01-01, ?due_before=2025-12-31

Ninja (Router)

Same endpoints at your configured path. All require authentication.

Linking to Other Models

Link a planner item to any model using linked_model + linked_object_id:

{
  "item_type": "task",
  "title": "Review meeting notes",
  "linked_model": "notes.Note",
  "linked_object_id": 42
}

Both fields are required together. The target model and object are validated on creation.

Signals

from django.dispatch import receiver
from nai_planner.signals import reminder_due

@receiver(reminder_due)
def handle_reminder(sender, user, item, **kwargs):
    # Send email, WebSocket, in-app notification, etc.
    pass

Fired when remind_at <= now and is_reminder_sent=False. The Celery task checks every 60 seconds (configurable).

Settings

Setting Default Description
NAI_PLANNER_FCM_ENABLED False Enable FCM push for reminders
NAI_PLANNER_FCM_CREDENTIALS_PATH None Path to Firebase credentials JSON
NAI_PLANNER_FCM_TOKEN_GETTER None Dotted path to token getter callable
NAI_PLANNER_REMINDER_CHECK_INTERVAL_SECONDS 60 How often Celery checks for due reminders
NAI_PLANNER_SOFT_DELETE True Enable soft delete (deleted_at)
NAI_PLANNER_USER_UUID_FIELD "uuid" User model UUID field for API lookups
NAI_PLANNER_DEFAULT_PRIORITY "medium" Default priority for new items

Development

# Clone and install with dev deps
git clone https://github.com/NEMATI-AI/nai-planner.git
cd nai-planner
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Lint
ruff check nai_planner/ tests/

# Format
ruff format nai_planner/ tests/

Project Structure

nai_planner/
├── contrib/
│   ├── drf/               # DRF ViewSet, serializers, filters, URLs
│   └── ninja/             # Ninja router, schemas
├── management/commands/   # setup_planner_beat
├── migrations/            # Django migrations
├── models/                # PlannerItem model + managers
├── admin.py               # Django admin config
├── apps.py                # NaiPlannerConfig
├── conf.py                # Centralised settings (NAI_PLANNER_* prefix)
├── signals.py             # reminder_due signal
└── tasks.py               # Celery task + FCM push helper
tests/
├── settings.py            # SQLite in-memory test config
├── test_models.py         # Model + manager tests
└── test_tasks.py          # Celery task + signal tests

License

MIT

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

nai_planner-0.1.1.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

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

nai_planner-0.1.1-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file nai_planner-0.1.1.tar.gz.

File metadata

  • Download URL: nai_planner-0.1.1.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for nai_planner-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ba7139a9740cb03e84c426ef081352741058cf7e216a5707f8e73c4a7fefba59
MD5 083b8de1001a3aa27dd3cb14cf4cfac2
BLAKE2b-256 10f9d8df522f8e4439cf2288109fd26687253650a5c944bfd5dfb48b104b8de6

See more details on using hashes here.

File details

Details for the file nai_planner-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: nai_planner-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for nai_planner-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4f6cfc4e6d36daba9fb5277f8472d208928a98711690822b65a0988f633462ac
MD5 dbff2a4061b2367eb171adf304d13c63
BLAKE2b-256 b21541ec6d38e74b788604b1335339d0acb0199941d65a778930d915eb0e28ab

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