• Stars
    star
    744
  • Rank 60,965 (Top 2 %)
  • Language
    Python
  • License
    MIT License
  • Created over 8 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

FCM Django: Send push notifications via django to websites, iOS & android mobile devices through FCM (Firebase Cloud Messaging)

fcm-django

Django app for Firebase Cloud Messaging. Used as an unified platform for sending push notifications to mobile devices & browsers (android / ios / chrome / firefox / ...).

Supports Firebase Cloud Messaging HTTP v1 API. If you're looking for the legacy API, use fcm-django<1!

FCMDevice model fields
  • registration_id (required - is FCM token)
  • name (optional)
  • active (default: true)
  • user (optional)
  • device_id (optional - can be used to uniquely identify devices)
  • type ('android', 'web', 'ios')
Functionality:
  • all necessary migrations
  • model admins for django admin
  • admin actions for testing single and bulk notification sending
  • automatic device pruning: devices to which notifications fail to send are marked as inactive
  • devices marked as inactive will not be sent notifications
  • Django rest framework viewsets

Demo javascript client project

Unsure how to use this project? Check out the demo at: https://github.com/xtrinch/fcm-django-web-demo

Migration to v1.0

We've replaced Python package pyfcm for Firebase's own package firebase-admin. Thus, we no longer use an API key. Instead, you'll need an environment variable GOOGLE_APPLICATION_CREDENTIALS which is a path pointing to your JSON-file stored credentials. To learn more or view other options to input credentials, visit the Google Cloud docs.

Finally, in your settings.py (or whatever imported file), add:

from firebase_admin import initialize_app
FIREBASE_APP = initialize_app()
# Or just
initialize_app()

The API for sending messages is now under the firebase-admin package; hence, we removed the methods send_data_message from the QuerySet and class instance methods. Instead, everything is under a single method: send_message

from firebase_admin.messaging import Message, Notification
FCMDevice.objects.send_message(Message(data=dict()))
# Note: You can also combine the data and notification kwarg
FCMDevice.objects.send_message(
    Message(notification=Notification(title="title", body="body", image="image_url"))
)
device = FCMDevice.objects.first()
device.send_message(Message(...))

Additionally, we've added Firebase's new Topic API, allowing for easier sending of bulk messages.

from firebase_admin.messaging import Message, Notification
topic = "A topic"
FCMDevice.objects.handle_subscription(True, topic)
FCMDevice.send_topic_message(Message(data={...}), "TOPIC NAME")

There are two additional parameters to both methods: skip_registration_id_lookup and additional_registration_ids. Visit Sending Messages to learn more.

Note: registration_ids is actually incorrect terminology as it should actually be called registration tokens. However, to be consistent with django-push-notifications, we've refrained from switching to stay backwards compatible in the docs and with the sister package.

Setup

You can install the library directly from pypi using pip:

pip install fcm-django

Edit your settings.py file:

from firebase_admin import initialize_app

INSTALLED_APPS = (
    ...
    "fcm_django"
    ...
)

# Optional ONLY IF you have initialized a firebase app already:
# Visit https://firebase.google.com/docs/admin/setup/#python
# for more options for the following:
# Store an environment variable called GOOGLE_APPLICATION_CREDENTIALS
# which is a path that point to a json file with your credentials.
# Additional arguments are available: credentials, options, name
FIREBASE_APP = initialize_app()
# To learn more, visit the docs here:
# https://cloud.google.com/docs/authentication/getting-started>

FCM_DJANGO_SETTINGS = {
     # an instance of firebase_admin.App to be used as default for all fcm-django requests
     # default: None (the default Firebase app)
    "DEFAULT_FIREBASE_APP": None,
     # default: _('FCM Django')
    "APP_VERBOSE_NAME": "[string for AppConfig's verbose_name]",
     # true if you want to have only one active device per registered user at a time
     # default: False
    "ONE_DEVICE_PER_USER": True/False,
     # devices to which notifications cannot be sent,
     # are deleted upon receiving error response from FCM
     # default: False
    "DELETE_INACTIVE_DEVICES": True/False,
}

Native Django migrations are in use. manage.py migrate will install and migrate all models.

Messages

You can read more about different types of messages here.

In short, there are two types: notifications and data messages.

Notification:

from firebase_admin.messaging import Message, Notification
Message(
    notification=Notification(title="title", body="text", image="url"),
    topic="Optional topic parameter: Whatever you want",
)

Data message:

from firebase_admin.messaging import Message
Message(
    data={
        "Nick" : "Mario",
        "body" : "great match!",
        "Room" : "PortugalVSDenmark"
   },
   topic="Optional topic parameter: Whatever you want",
)

As in the following example, you can send either a notification, a data message, or both. You can also customize the Android, iOS, and Web configuration along with additional FCM conditions. Visit firebase_admin.messaging.Message to learn more about those configurations.

Sending messages

Additional parameters are additional_registration_ids and skip_registration_id_lookup. View the "Additional Parameters" section for more information.

from firebase_admin.messaging import Message
from fcm_django.models import FCMDevice

# You can still use .filter() or any methods that return QuerySet (from the chain)
device = FCMDevice.objects.all().first()
# send_message parameters include: message, dry_run, app
device.send_message(Message(data={...}))

Sending messages in bulk

from firebase_admin.messaging import Message
from fcm_django.models import FCMDevice

# You can still use .filter() or any methods that return QuerySet (from the chain)
devices = FCMDevice.objects.all()
devices.send_message(Message(data={...}))
# Or (send_message parameters include: messages, dry_run, app)
FCMDevice.objects.send_message(Message(...))

Sending messages raises all the errors that firebase-admin raises, so make sure they are caught and dealt with in your application code:

  • FirebaseError – If an error occurs while sending the message to the FCM service.
  • ValueError – If the input arguments are invalid.

For more info, see https://firebase.google.com/docs/reference/admin/python/firebase_admin.messaging#firebase_admin.messaging.BatchResponse

Subscribing or Unsubscribing Users to topic

from fcm_django.models import FCMDevice

# Subscribing
FCMDevice.objects.all().handle_topic_subscription(True, topic="TOPIC NAME"))
device = FCMDevice.objects.all().first()
device.handle_topic_subscription(True, topic="TOPIC NAME"))

# Finally you can send a message to that topic
from firebase_admin.messaging import Message
message = Message(..., topic="A topic")
# You can still use .filter() or any methods that return QuerySet (from the chain)
FCMDevice.objects.send_message(message)

# Unsubscribing
FCMDevice.objects.all().handle_topic_subscription(False, topic="TOPIC NAME"))
device = FCMDevice.objects.all().first()
device.handle_topic_subscription(False, topic="TOPIC NAME"))

Sending messages to topic

from fcm_django.models import FCMDevice

FCMDevice.send_topic_message(Message(data={...}), "TOPIC NAME")

Additional Parameters

You can add additional_registration_ids (Sequence) for manually sending registration IDs. It will append these IDs to the queryset lookup's returned registration IDs.

You can also add skip_registration_id_lookup (bool) to skip database lookup that goes along with your query.

from firebase_admin.messaging import Message
from fcm_django.models import FCMDevice
FCMDevice.objects.send_message(Message(...), False, ["registration_ids"])

Using multiple FCM apps

By default the message will be sent using the default FCM firebase_admin.App (we initialized this in our settings), or the one specified with the DEFAULT_FIREBASE_APP setting.

This default can be overridden by specifying an app when calling send_message. This can be used to send messages using different firebase projects.

from firebase_app import App
from firebase_app.messaging import Notification
from fcm_django.models import FCMDevice

device = FCMDevice.objects.all().first()
device.send_message(notification=Notification(...), app=App(...))

Setting a default Firebase app for FCM

If you want to use a specific Firebase app for all fcm-django requests, you can create an instance of firebase_admin.App and pass it to fcm-django with the DEFAULT_FIREBASE_APP setting.

The DEFAULT_FIREBASE_APP will be used for all send / subscribe / unsubscribe requests, include FCMDevice's admin actions.

In your settings.py:

from firebase_admin import initialize_app, credentials
from google.auth import load_credentials_from_file
from google.oauth2.service_account import Credentials

# create a custom Credentials class to load a non-default google service account JSON
class CustomFirebaseCredentials(credentials.ApplicationDefault):
    def __init__(self, account_file_path: str):
        super().__init__()
        self._account_file_path = account_file_path

    def _load_credential(self):
        if not self._g_credential:
            self._g_credential, self._project_id = load_credentials_from_file(self._account_file_path,
                                                                              scopes=credentials._scopes)

# init default firebase app
# this loads the default google service account with GOOGLE_APPLICATION_CREDENTIALS env variable
FIREBASE_APP = initialize_app()

# init second firebase app for fcm-django
# the environment variable contains a path to the custom google service account JSON
custom_credentials = CustomFirebaseCredentials(os.getenv('CUSTOM_GOOGLE_APPLICATION_CREDENTIALS'))
FIREBASE_MESSAGING_APP = initialize_app(custom_credentials, name='messaging')

FCM_DJANGO_SETTINGS = {
    "DEFAULT_FIREBASE_APP": FIREBASE_MESSAGING_APP,
    # [...] your other settings
}

Django REST Framework (DRF) support

Viewsets come in two different varieties:

  • FCMDeviceViewSet

    • Permissions as specified in settings (AllowAny by default, which is not recommended)
    • A device may be registered without associating it with a user
    • Will not allow duplicate registration_id's
  • FCMDeviceAuthorizedViewSet

    • Permissions are IsAuthenticated and custom permission IsOwner, which will only allow the request.user to get and update devices that belong to that user
    • Requires a user to be authenticated, so all devices will be associated with a user
    • Will update the device on duplicate registration id

Routes can be added one of two ways:

from fcm_django.api.rest_framework import FCMDeviceAuthorizedViewSet

from rest_framework.routers import DefaultRouter

router = DefaultRouter()

router.register('devices', FCMDeviceAuthorizedViewSet)

urlpatterns = [
    # URLs will show up at <api_root>/devices
    # DRF browsable API which lists all available endpoints
    path('', include(router.urls)),
    # ...
]
  • Using as_view (specify which views to include)
from fcm_django.api.rest_framework import FCMDeviceAuthorizedViewSet

urlpatterns = [
    # Only allow creation of devices by authenticated users
    path('devices', FCMDeviceAuthorizedViewSet.as_view({'post': 'create'}), name='create_fcm_device'),
    # ...
]

Update of device with duplicate registration ID

Tokens are device specific, so if the user e.g. logs out of their account on your device, and another user logins on the same device, you do not wish the old user to receive messages while logged out.

Via DRF, any creation of device with an already existing registration ID will be transformed into an update. If done manually, you are responsible for deleting the old device entry.

Python 3 support

Django version compatibility

Compatible with Django versions 3.0+. For Django version 2.2, use version fcm-django < 1.0.13. For lower django versions, use version fcm-django < 1.0.0.

Acknowledgements

Library relies on firebase-admin-sdk for sending notifications, for more info about all the possible fields, see: https://github.com/firebase/firebase-admin-python

Migration from v0 to v1 was done by Andrew-Chen-Wang

Need help, have any questions, suggestions?

Submit an issue/PR on this project. Please do not send me emails, as then the community has no chance to see your questions / provide answers.

Contributing

To setup the development environment, simply do pip install -r requirements_dev.txt To manually run the pre-commit hook, run pre-commit run --all-files.

More Repositories

1

MRCountryPicker

iOS Country picker with flags and optionally phone numbers written in Swift. Swift 4 compatible.
Swift
75
star
2

fcm-django-web-demo

Quick demo to demonstrate the use of firebase web push notifications with the use of `javascript` on frontend, `django` on backend and push notifications via `fcm-django` pypi package for django.
HTML
63
star
3

react-touch-screen-keyboard

React touch screen virtual keyboard, opened on input focused
JavaScript
47
star
4

go-react-todo

Todo REST API written in Go, React frontend client, setup using docker & docker-compose.
JavaScript
40
star
5

moka7-live

S7 PLC communication library for Java, based on Moka7
Java
38
star
6

jwt-express-react-example

Example "popularity" app developed with React & Express & Passport & Node
JavaScript
21
star
7

KeyboardLayoutHelper

Keyboard layout constraint class for iOS written in Swift to help adapt UIView to the appearing keyboard, so textfields don't get lost underneath it'.
Swift
17
star
8

sensor-dashboard-nestjs-backend

Nest.JS Backend repo for a grafana-like environmental sensor dashboard.
TypeScript
9
star
9

node-react-sockjs-chat

Realtime chat application featuring Node.js as the backend server, SockJS for handling socket connections and React on the frontend.
JavaScript
9
star
10

socket-live

Java TCP/IP socket communication library
Java
9
star
11

update-motd.d

Motd parts written in bash (Includes welcome message, system info and "inspirational" footer)
Shell
9
star
12

ansible-role-kiosk

Ansible role for creating website kiosk out of ubuntu/debian server with a light stack of X and openbox
Shell
9
star
13

sx127x-node-driver

Node.js driver for Semtech SX1276/77/78/79 LoRa circuits
JavaScript
8
star
14

vhdl-snake

Snake game with PS2 and VGA drivers written in VHDL for the Nexys 2 development board
VHDL
6
star
15

python-zebra-scanner

Barcode reader driver in python for Zebra LI3678 Linear Imager.
Python
6
star
16

stratumv2-python-miner

Stratum v2 bitcoin miner written in python
Python
5
star
17

fpga-bitcoin-miner

FPGA bitcoin miner for the Lattice ECP5 evaluation board.
Verilog
5
star
18

sensor-dashboard-react-frontend

Frontend repo for a grafana-like environmental sensor dashboard.
TypeScript
5
star
19

pascal-compiler

Pascal compiler written in Java
Java
5
star
20

sails-pagination-middleware

Sails 1.x pagination middleware or hook returning total count in a transformed JSON response
JavaScript
5
star
21

esp-weather-station

OpenWeatherMap & IotFreezer weather station running on ESP32/8266 and a TFT display
C++
5
star
22

create-react-app-module-federation-example

An example repo on how to use module federation with apps jumpstarted by create-react-app without ejecting the configuration
HTML
4
star
23

ESP-internet-radio

Internet radio station using an ESP32, VS1053 module, a TFT ILI9341 screen and an IR sensor.
C++
4
star
24

stm32f7-demos

Demo projects using various HAL, BSP & LL libraries from STM32F7Cube framework
C
4
star
25

MRMultipleContactPicker

Choose multiple contacts, ios 8.0+ compatible, swift 2.3
Swift
4
star
26

fractal_generator

Java desktop application written and designed with Netbeans for generating different types of fractal images.
Java
4
star
27

sails-hook-validation-ev

Sails 1.x validation hook using express-validate functions
JavaScript
4
star
28

STM32F7-template

Build template for the STM32F7 microprocessor
C
3
star
29

django-docker-example

Sample project with docker-compose using django and postgres
Python
3
star
30

esp32s2-bme280-webusb

A web-usb enabled application running on ESP32S2 supporting displaying sensor data on a Waveshare e-paper display / sending sensor data to the cloud
C++
3
star
31

MRPullToRefreshLoadMore

Easy and simple way to add pull to refresh and load more for table views, collection views and even scrollviews
Swift
3
star
32

arduino-buzzer-slovenian-anthem

Slovenian anthem played on piezzo buzzer controlled with arduino
C++
3
star
33

MRTableViewCellCountScrollIndicator

iOS Table View Cell Scroll Count Indicator
Swift
3
star
34

vue-sails-todo

Todo app developed with sails.js and vue.js
JavaScript
3
star
35

arduino-hall-sensors

C++
3
star
36

vue-express-mongo-todo

Todo app written with Vue.js, Express & mongodb
JavaScript
2
star
37

archicad-atrium-house

Plans for a 2-bedroom atrium house created in Archicad
2
star
38

webusb-arduino-react-example

Example app demonstrating the use of webusb to toggle some LED's from web -> arduino.
C++
2
star
39

npm-react-module-boilerplate

Boilerplate for creating a React.js npm module
JavaScript
2
star
40

ark-blockchain-sensors-browser

Browse ARK blockchain sensor data
TypeScript
2
star
41

ESP-make-easy

Library that makes WiFi station mode, WiFi AP mode, sleep, EEPROM handling & resetting config on button press on ESP easier
C++
2
star
42

esp32-ark-blockchain-sender

Sends transactions to ARK blockchain
C++
2
star
43

ESP-BME680-reader

ESP board reads BME680 sensor data and sends it to the cloud
C++
2
star
44

TappyDefender

Android game with custom game engine where you avoid enemies by tapping to reach the finish line as fast as you can.
Java
2
star
45

icestick-fpga-uart

UART + UART packets encoding/decoding + pc reader program for Lattice icestick
Verilog
2
star
46

ESP-BME280-reader

Reads sensor data from Bosch BME280 and periodically sends it to the cloud
C++
2
star
47

wordpress-theme-trina

(archive) Wordpress theme for http://trina.si
PHP
1
star
48

ne555-flasher-circuit

ne555 drawn with Eagle
1
star
49

arduino-processing-flame-sensor

Processing
1
star
50

java-dynamic-class-reloading

Example project testing java dynamic class reloading
Java
1
star
51

ESP-lora-DHT11-reader

Reads DHT11 measurements and sends them to a LoRa (not LoRaWan!) gateway
C++
1
star
52

yocto-a10-olinuxino-lime-sato

Basic setup for poky distribution of yocto, enough to build the sato image for A10 olinuxino lime board
1
star
53

react-fabricjs-demo

2d floor planner with fabric.js & react (simplified version)
TypeScript
1
star
54

parametric-display-casing

Parametric casing for any kind of display; drawn in FreeCAD
G-code
1
star
55

vagrant-mongo-node-react-seed

Seed project using debian with vagrant, mongo, nodejs and reactjs
JavaScript
1
star
56

sweethome3d-house-plans

House plans drawn in free program SweetHome3D
1
star
57

ESP-lora-DHT11-sender

Reads DHT11 humidity & temperature data and sends it to another LoRa node
C++
1
star
58

arduino-analog-temperature-sensor

Analog temperature sensor with arduino
C++
1
star
59

ESP-lora-gateway

Lora (not LoraWan!) gateway, receives messages via LoRa and forwards them to the cloud
C++
1
star
60

maribor-city-park-cad-map

Map of walkways in Maribor city park in Autocad
1
star
61

raycaster

Typescript rewrite of playful-js's raycaster
TypeScript
1
star
62

parallel-reversi

AI reversi player, parallelized with MPI and pThreads
C++
1
star
63

icestick-fpga-example

Example project for Lattice icestick fpga
Verilog
1
star
64

homeassistant-example

Showcases a docker-compose setup for one local sensor within homeassistant sending data via MQTT (running in a container via docker-compose)
1
star
65

sensor-dashboard-oled-display

ESP32 board with PCD8544 attached reads sensor data from the cloud and displays it on the screen
C++
1
star
66

node-koofr-uploader

Uploads files to koofr
TypeScript
1
star
67

arduino-multiple-servos-example

Test project for multiple servos with Arduino Uno
C++
1
star
68

ansible-role-backup-file

Regularly create local backup of file in filesystem
1
star
69

trina.si

Source code for personal website
TypeScript
1
star
70

tetris-rust

Tetris game written in rust
Rust
1
star