{"id":9742,"library":"fcm-django","title":"FCM Django","description":"fcm-django provides a convenient way to integrate Firebase Cloud Messaging (FCM) into Django applications, allowing developers to send push notifications to mobile devices and web browsers. It simplifies device registration and message dispatching. The current version is 3.2.0, and the library maintains an active development cycle with frequent releases addressing new features and compatibility updates.","status":"active","version":"3.2.0","language":"en","source_language":"en","source_url":"https://github.com/xtrinch/fcm-django","tags":["django","fcm","firebase","notifications","push-notifications","mobile","web"],"install":[{"cmd":"pip install fcm-django","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core framework integration for FCMDevice model and Django settings.","package":"Django"},{"reason":"Required for interacting with Firebase Cloud Messaging API.","package":"firebase-admin"}],"imports":[{"symbol":"FCMDevice","correct":"from fcm_django.models import FCMDevice"},{"note":"These are from the underlying 'firebase-admin' library, but essential for constructing messages.","symbol":"Message, Notification","correct":"from firebase_admin.messaging import Message, Notification"}],"quickstart":{"code":"import os\nfrom django.conf import settings\nfrom fcm_django.models import FCMDevice\nfrom firebase_admin.messaging import Message, Notification\n\n# --- Configure Django settings (this would typically be in your settings.py) ---\n# For a runnable example, we configure it on the fly.\n# Replace with your actual Firebase project credentials or use environment variables.\n# Set environment variables for actual testing, e.g., in your shell:\n# export FCM_PROJECT_ID=\"your-firebase-project-id\"\n# export FCM_PRIVATE_KEY=\"-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----\\n\"\n# export FCM_CLIENT_EMAIL=\"firebase-adminsdk@your-project-id.iam.gserviceaccount.com\"\n# export FCM_TEST_DEVICE_TOKEN=\"your_actual_device_token_from_client_app\"\n\nif not settings.configured:\n    settings.configure(\n        INSTALLED_APPS=[\n            'django.contrib.auth', # Required for user foreign key in FCMDevice\n            'django.contrib.contenttypes',\n            'fcm_django'\n        ],\n        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},\n        DEBUG=True,\n        SECRET_KEY='a-very-secret-key-for-example', # Placeholder for runnable example\n        FCM_DJANGO_SETTINGS={\n            \"FIREBASE_ADMIN_CREDENTIALS\": {\n                \"type\": \"service_account\",\n                \"project_id\": os.environ.get(\"FCM_PROJECT_ID\", \"your-firebase-project-id\"),\n                \"private_key_id\": os.environ.get(\"FCM_PRIVATE_KEY_ID\", \"your-private-key-id\"),\n                \"private_key\": os.environ.get(\"FCM_PRIVATE_KEY\", \"-----BEGIN PRIVATE KEY-----\\nPLACE_YOUR_PRIVATE_KEY_HERE\\n-----END PRIVATE KEY-----\\n\").replace(\"\\\\n\", \"\\n\"),\n                \"client_email\": os.environ.get(\"FCM_CLIENT_EMAIL\", \"firebase-adminsdk@your-project-id.iam.gserviceaccount.com\"),\n                \"client_id\": os.environ.get(\"FCM_CLIENT_ID\", \"12345678901234567890\"),\n                \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n                \"token_uri\": \"https://oauth2.googleapis.com/token\",\n                \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n                \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk%40your-project-id.iam.gserviceaccount.com\"\n            }\n            # Alternatively, specify a path to your service account JSON file:\n            # \"FIREBASE_ADMIN_CREDENTIALS_FILE\": os.environ.get(\"FCM_CREDENTIALS_PATH\", None)\n        }\n    )\n\n    # Initialize Django apps system and create tables for fcm_django model\n    import django\n    django.setup()\n    from django.db import connection\n    with connection.schema_editor() as schema_editor:\n        try:\n            schema_editor.create_model(FCMDevice)\n        except Exception as e:\n            # Ignore if table already exists, common in re-runs of snippet\n            if 'already exists' not in str(e):\n                raise\n\n# --- Your application logic (e.g., in a view, management command, or script) ---\n\n# This token would come from your client-side Firebase SDK.\n# Replace with a real FCM device token for actual testing.\ndevice_token = os.environ.get(\"FCM_TEST_DEVICE_TOKEN\", \"YOUR_FCM_DEVICE_TOKEN_HERE\")\nuser = None # Link to a Django User model instance if available\n\nif \"YOUR_FCM_DEVICE_TOKEN_HERE\" in device_token:\n    print(\"Warning: Please replace 'YOUR_FCM_DEVICE_TOKEN_HERE' with an actual device token from your client-side app.\")\n    print(\"         Without a valid token, no notification will be sent.\")\n\n# Register or get an FCM device\ndevice, created = FCMDevice.objects.get_or_create(\n    registration_id=device_token,\n    defaults={\n        \"name\": \"Test Device\",\n        \"active\": True,\n        \"type\": \"android\" # or 'ios', 'web'\n    }\n)\n\nif created:\n    print(f\"Registered new FCM device: {device.registration_id}\")\nelse:\n    print(f\"FCM device already registered or updated: {device.registration_id}\")\n\n# Send a notification to the device\ntry:\n    # Using FCMDeviceQuerySet.send_message for convenience and bulk support\n    response = FCMDevice.objects.filter(id=device.id).send_message(\n        title=\"Hello from FCM-Django!\",\n        body=\"This is a test push notification sent via FCM.\",\n        data={\"custom_key\": \"custom_value\"}, # Optional data payload\n        sound=\"default\" # Optional sound\n    )\n    print(f\"Notification sent successfully: {response}\")\n\nexcept Exception as e:\n    print(f\"Error sending notification: {e}\")\n    if \"InvalidRegistration\" in str(e) or \"NotFoundError\" in str(e):\n        print(\"This often means the device token is invalid or expired. Ensure 'YOUR_FCM_DEVICE_TOKEN_HERE' is current.\")\n    elif \"default app has not been initialized\" in str(e):\n        print(\"Firebase Admin SDK not initialized. Check FCM_DJANGO_SETTINGS configuration.\")\n","lang":"python","description":"This quickstart demonstrates how to configure `fcm-django` settings, register a device, and send a push notification. It includes a self-contained Django settings configuration for easy execution. Remember to replace placeholder credentials and device tokens with your actual Firebase project details and a valid client-side FCM token for successful testing."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or newer, or pin `fcm-django` to a version less than 3.0.0 (e.g., `fcm-django<3.0.0`) if you must use Python 3.9.","message":"Python 3.9 support was dropped in `fcm-django` 3.0.0. The minimum supported Python version is now 3.10.","severity":"breaking","affected_versions":"3.0.0+"},{"fix":"Upgrade your Python environment to 3.7+ (for 2.x versions) or 3.10+ (for 3.x versions), or pin `fcm-django` to `<2.0.0` for Python 3.6.","message":"Python 3.6 support was dropped in `fcm-django` 2.0.0. Older Python versions must use `fcm-django <2.0.0`.","severity":"breaking","affected_versions":"2.0.0+"},{"fix":"Ensure you are using `fcm-django` 2.1.0 or newer, as it updates its internal calls to use `send_each()`. If directly using `firebase_admin.messaging`, switch from `send_all` to `send_each`.","message":"The underlying `firebase-admin` library deprecated `send_all()` in favor of `send_each()` for sending messages to multiple tokens. `fcm-django` versions prior to 2.1.0 might still use the deprecated method, which could lead to warnings or unexpected behavior with newer `firebase-admin` versions.","severity":"deprecated","affected_versions":"<2.1.0"},{"fix":"Add `FCM_DJANGO_SETTINGS = {'MYSQL_COMPATIBILITY': True}` to your Django `settings.py` *before* running migrations. This removes the unique constraint from the `registration_id` field. Alternatively, ensure your MySQL configuration (e.g., `innodb_large_prefix=1` and `ROW_FORMAT=DYNAMIC` for InnoDB tables) supports longer keys.","message":"For MySQL databases, unique constraints on `registration_id` (a TextField) can exceed the maximum key length (767 bytes) for default `ROW_FORMAT` settings. This can cause migration failures.","severity":"gotcha","affected_versions":"All versions with MySQL"},{"fix":"Carefully review and configure `FCM_DJANGO_SETTINGS` in your `settings.py`, ensuring `FIREBASE_ADMIN_CREDENTIALS` contains the correct service account JSON dictionary or `FIREBASE_ADMIN_CREDENTIALS_FILE` points to a valid service account JSON file.","message":"`FCM_DJANGO_SETTINGS` in `settings.py` must be correctly configured with valid Firebase Admin SDK credentials (e.g., `FIREBASE_ADMIN_CREDENTIALS` or `FIREBASE_ADMIN_CREDENTIALS_FILE`). Misconfiguration or missing settings will prevent `fcm-django` from initializing Firebase and will lead to runtime errors when attempting to send messages.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Run `pip install fcm-django` to install the package.","cause":"The `fcm-django` package is not installed or not available in the current Python environment.","error":"ModuleNotFoundError: No module named 'fcm_django'"},{"fix":"Add a valid `FCM_DJANGO_SETTINGS` dictionary to your `settings.py`, containing the Firebase Admin SDK credentials, e.g., `FCM_DJANGO_SETTINGS = {\"FIREBASE_ADMIN_CREDENTIALS\": {...}}`.","cause":"The `FCM_DJANGO_SETTINGS` dictionary is missing or incorrectly defined in your Django project's `settings.py`.","error":"django.core.exceptions.ImproperlyConfigured: FCM_DJANGO_SETTINGS must be configured."},{"fix":"Add `FCM_DJANGO_SETTINGS = {'MYSQL_COMPATIBILITY': True}` to your `settings.py` before running Django migrations. This setting removes the unique constraint from the problematic field.","cause":"This error occurs with MySQL databases when a unique index on the `registration_id` (a TEXT field) exceeds MySQL's default key length limit.","error":"django.db.utils.ProgrammingError: (1071, 'Specified key was too long; max key length is 767 bytes')"},{"fix":"Verify that `fcm_django` is included in `INSTALLED_APPS` and that `FCM_DJANGO_SETTINGS` is correctly configured in your `settings.py`.","cause":"The Firebase Admin SDK has not been correctly initialized. While `fcm-django` usually handles this internally upon first access, it can indicate a problem with `FCM_DJANGO_SETTINGS` or an unusual import order.","error":"RuntimeError: The app default app has not been initialized. Make sure to call initialize_app() before using any of the Firebase services."}]}