Skip to main content

SmoothGlue Calendar

smoothglue_calendar is a Django app that provides a flexible and extensible calendar solution for the SmoothGlue ecosystem. It allows you to create and manage calendar events, define custom event types, and link events to any other Django model.

By attaching any object to an CalendarEvent object approach, the event start-end times will be centralized in a single model/table, making it easier and faster to query the event data. This approach allows faster deconfliction of scheduling data since everything is in the same table.

Features

  • Calendar Events: Create, retrieve, update, and delete calendar events with start and end times, a name, and a description.
  • Custom Event Types: Define your own event types to categorize events.
  • Generic Relations: Link calendar events to any other Django model using generic foreign keys.
  • Dynamic Serializers: Specify a serializer for each event type to control the representation of the related object.
  • Filtering: Filter events by event_type and for overlapping date ranges.

Model ERD for SmoothGlue Calendar

erDiagram
    CalendarEvent {
        UUID id PK
        string event_name
        datetime start_time
        datetime end_time
        UUID event_type_id FK
        integer content_type_id FK
        UUID object_id
    }
    EventType {
        UUID id PK
        string name
    }    EventType ||--|{ CalendarEvent : "is of type"
    CalendarEvent }o--|| Meeting : "can point to"
    CalendarEvent }o--|| PlatformUser : "can point to"
    CalendarEvent }o--|| Conference : "can point to"
    CalendarEvent }o--|| AnyOtherModel : "can point to"

Installation

  1. Add smoothglue_calendar to your INSTALLED_APPS in your Django settings file:

    INSTALLED_APPS = [
        ...
        'smoothglue.calendar',
        ...
    ]
    
  2. Include the calendar's URLs in your project's urls.py:

    from django.urls import include, path
    
    urlpatterns = [
        ...
        path('api/calendar/', include('smoothglue_calendar.urls')),
        ...
    ]
    
  3. Run migrations to create the calendar models:

    python manage.py migrate smoothglue_calendar
    

Usage

API Endpoints

  • api/calendar/calendar-events/:
    • GET: List all calendar events.
      • Query Parameters:
        • event_type: Filter by the UUID of an EventType.
        • range_start: The start of a date range (ISO 8601 format).
        • range_end: The end of a date range (ISO 8601 format).
        • object_id: Filter by the UUID of a related object.
        • year: Filter by year on either the start_time or end_time.
        • month: Filter by month (1-12) on either the start_time or end_time.
        • day: Filter by day (1-31) on either the start_time or end_time. The range_start and range_end parameters will return any events that overlap with the specified date range.
    • POST: Create a new calendar event.
  • api/calendar/calendar-events/{id}/:
    • GET: Retrieve a specific calendar event.
    • PUT/PATCH: Update a specific calendar event.
    • DELETE: Delete a specific calendar event.
    • POST /archive/: Archives the event.
    • POST /unarchive/: Unarchives the event.
  • api/calendar/event-types/:
    • GET: List all event types.
    • POST: Create a new event type.

Creating Custom Event Types with Fixtures

You can create custom event types by loading a fixture file. This is useful for pre-populating your database with the event types your application needs.

To allow other applications to link their models to calendar events, you can specify a content_type_serializer for an EventType. This serializer will be used to represent the related object in the CalendarEvent API responses.

Example Fixture (event_types.json):

[
  {
    "model": "smoothglue_calendar.eventtype",
    "pk": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
    "fields": {
      "name": "Meeting",
      "description": "A standard meeting event.",
      "content_type_serializer": "some_app.serializers.MeetingSerializer"
    }
  },
  {
    "model": "smoothglue_calendar.eventtype",
    "pk": "b2c3d4e5-f6a7-8901-2345-67890abcdef1",
    "fields": {
      "name": "Exercise",
      "description": "A training exercise event."
    }
  }
]

To load the fixture, run the following command:

python manage.py loaddata event_types.json

This will create the "Meeting" and "Exercise" event types. The "Meeting" event type is configured to use the MeetingSerializer to represent its related objects, allowing for rich, domain-specific data to be included in the calendar API.

Advanced Configuration

Pluggable Queryset

The CalendarEventViewSet supports a pluggable get_queryset implementation, allowing you to customize the queryset based on your application's needs, such as applying custom permissions or prefetching related data.

To use a custom queryset function, define SG_CALENDAR_SETTINGS in your Django settings file:

SG_CALENDAR_SETTINGS = {
    "CALENDAR_VIEWSET_QUERYSET_FN": "path.to.your.custom_queryset_function"
}

Your custom function must accept two arguments: the request object and the default_queryset. It should return a QuerySet object.

Example Custom Function:

def get_events_for_user(request, default_queryset):
    return default_queryset.filter(created_by=request.user)

Pluggable Permissions

Similar to the queryset, you can inject custom permission classes into the CalendarEventViewSet. This allows you to enforce specific access controls, such as role-based access or object-level permissions.

To use custom permission classes, update SG_CALENDAR_SETTINGS in your Django settings file:

SG_CALENDAR_SETTINGS = {
    "CALENDAR_VIEWSET_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
        "path.to.your.CustomPermission",
    ]
}

Example Custom Permission:

from rest_framework import permissions

class CalendarEventPermission(permissions.BasePermission):
    """
    A single, consolidated permission class for the CalendarEvent model.
    """

    def has_permission(self, request, view):
        """
        Handles model-level permissions (for list/create actions).
        """
        if not request.user or not request.user.is_authenticated:
            return False

        if view.action == "list":
            return request.user.has_perm("your_app.view_calendar")

        if view.action == "create":
            event_type_name = request.data.get("event_type_name")
            if event_type_name == "Personnel":
                self.message = "You do not have permission to add new personnel events."
                return request.user.has_perm("your_app.add_personnel_event")
            
            return request.user.has_perm("your_app.add_event")

        return True

    def has_object_permission(self, request, view, obj):
        """
        Dispatches to the appropriate helper method based on the action.
        """
        action_handlers = {
            "retrieve": self._can_retrieve,
            "update": self._can_update,
            "partial_update": self._can_update,
            "destroy": self._can_archive,
            "archive": self._can_archive,
            "unarchive": self._can_archive,
        }

        handler = action_handlers.get(view.action)
        if handler:
            return handler(request, obj)

        return False

    def _can_retrieve(self, request, obj):
        return request.user.has_perm("your_app.view_calendar", obj)

    def _can_update(self, request, obj):
        if obj.event_type.name == "Personnel":
            return request.user.has_perm("your_app.change_personnel_event", obj)
        return request.user.has_perm("your_app.change_event", obj)

    def _can_archive(self, request, obj):
        if obj.event_type.name == "Personnel":
            return request.user.has_perm("your_app.archive_personnel_event", obj)
        return request.user.has_perm("your_app.archive_event", obj)

Release files for smoothglue_calendar 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for smoothglue_calendar 1.0.1
File Size Uploaded
smoothglue_calendar-1.0.1.tar.gz 17.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for smoothglue_calendar 1.0.1
File Interpreter ABI Platform
smoothglue_calendar-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 39.9 kB

Release files / smoothglue_calendar-1.0.1.tar.gz

Download URL smoothglue_calendar-1.0.1.tar.gz
Size 17.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ab579a8bad0bc20148f2b2f84b959065957f314703d3e575f8c7262deb868403
BLAKE2b-256 checksum
How to use checksums
bf45572c81811be9f07e8c515d5f74e58985d79a20095ba8eeec2097bcc7659b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.11 Linux/4.18.0-553.51.1.el8_10.x86_64

Release files / smoothglue_calendar-1.0.1-py3-none-any.whl

Download URL smoothglue_calendar-1.0.1-py3-none-any.whl
Size 22.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cb835b256bdf8f65f5c8983521d9bb7d0109ae8fae99fe58a379986188c6392b
BLAKE2b-256 checksum
How to use checksums
39742b7c82be1d7ee02d21fed4a0d998237e04f4f64ec7429ecd94c5083a189c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.11 Linux/4.18.0-553.51.1.el8_10.x86_64

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page