Skip to main content

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

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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page