Skip to main content

SmoothGlue Calendar: A reusable Django app for calendar functionality.

Project description

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)

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

smoothglue_calendar-1.0.1.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

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

smoothglue_calendar-1.0.1-py3-none-any.whl (22.2 kB view details)

Uploaded Python 3

File details

Details for the file smoothglue_calendar-1.0.1.tar.gz.

File metadata

  • Download URL: smoothglue_calendar-1.0.1.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.12.11 Linux/4.18.0-553.51.1.el8_10.x86_64

File hashes

Hashes for smoothglue_calendar-1.0.1.tar.gz
Algorithm Hash digest
SHA256 ab579a8bad0bc20148f2b2f84b959065957f314703d3e575f8c7262deb868403
MD5 86623880f1a0b2ae9a47312992b05498
BLAKE2b-256 bf45572c81811be9f07e8c515d5f74e58985d79a20095ba8eeec2097bcc7659b

See more details on using hashes here.

File details

Details for the file smoothglue_calendar-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: smoothglue_calendar-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 22.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.12.11 Linux/4.18.0-553.51.1.el8_10.x86_64

File hashes

Hashes for smoothglue_calendar-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cb835b256bdf8f65f5c8983521d9bb7d0109ae8fae99fe58a379986188c6392b
MD5 488f4fd5b56899c313cd4902f9759b90
BLAKE2b-256 39742b7c82be1d7ee02d21fed4a0d998237e04f4f64ec7429ecd94c5083a189c

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