跳转到主要内容

通过GCM、APNS或WNS将推送通知发送到移动设备,并通过WebPush(Chrome、Firefox和Opera)在Django中发送

项目描述

Jazzband GitHub Actions Code coverage

一个最小的Django应用程序,实现了可以发送通过APNS、FCM/GCM、WNS和WebPush的消息的设备模型。

该应用程序实现了四个模型:GCMDeviceAPNSDeviceWNSDeviceWebPushDevice。这些模型具有相同的属性
  • name (可选): 设备名称。

  • active (默认 True): 一个布尔值,用于确定设备是否会收到通知。

  • user (可选): 对 auth.User 的外键,如果您希望将设备链接到特定用户。

  • device_id (可选): 从 Android/iOS/Windows API 获取的设备 UUID,如果您希望唯一标识它。

  • registration_id (必需): 设备的 FCM/GCM 注册 id 或 APNS 令牌。

应用程序还实现了管理员面板,您可以通过该面板测试单个和批量通知。选择一个或多个 FCM/GCM、APNS、WNS 或 WebPush 设备,然后在操作下拉菜单中,根据需要选择“发送测试消息”或“批量发送测试消息”。请注意,向多个设备发送非批量测试消息将仅遍历设备并发送多个单条消息。UPDATE_ON_DUPLICATE_REG_ID:将基于注册 id 的现有 Device(创建)转换为更新。有关详细信息,请参阅下文 更新具有重复注册 ID 的设备

依赖关系

  • Python 3.7+

  • Django 2.2+

  • 对于 API 模块,需要 Django REST Framework 3.7+。

  • 对于 WebPush (WP),需要 pywebpush 1.3.0+(可选)。生成 WebPush 私钥需要 py-vapid 1.3.0+;然而,这一步骤不需要在应用程序服务器上执行。

  • 对于 Apple Push (APNS),需要 apns2 0.3+(可选)。

  • 对于 FCM,需要 firebase-admin 6.2+(可选)。

设置

您可以直接使用 pip 从 PyPI 安装库

$ pip install django-push-notifications[WP,APNS,FCM]

编辑您的 settings.py 文件

INSTALLED_APPS = (
        ...
        "push_notifications"
)

# Import the firebase service
from firebase_admin import auth

# Initialize the default app (either use `GOOGLE_APPLICATION_CREDENTIALS` environment variable, or pass a firebase_admin.credentials.Certificate instance)
default_app = firebase_admin.initialize_app()

PUSH_NOTIFICATIONS_SETTINGS = {
        "APNS_CERTIFICATE": "/path/to/your/certificate.pem",
        "APNS_TOPIC": "com.example.push_test",
        "WNS_PACKAGE_SECURITY_ID": "[your package security id, e.g: 'ms-app://e-3-4-6234...']",
        "WNS_SECRET_KEY": "[your app secret key, e.g.: 'KDiejnLKDUWodsjmewuSZkk']",
        "WP_PRIVATE_KEY": "/path/to/your/private.pem",
        "WP_CLAIMS": {'sub': "mailto:development@example.com"}
}

有关如何生成证书的更多信息,请参阅 docs/APNS

您可以在 此处 了解更多有关 APNS 证书的信息。

使用原生 Django 迁移。执行 manage.py migrate 将安装和迁移所有模型。

设置列表

所有设置都包含在 PUSH_NOTIFICATIONS_SETTINGS 字典中。

对于 APNS,您需要包含 APNS_CERTIFICATE。对于 WNS,您需要 WNS_PACKAGE_SECURITY_KEYWNS_SECRET_KEY

通用设置

  • USER_MODEL:您选择的用户模型。例如,myapp.User。默认为 settings.AUTH_USER_MODEL

  • UPDATE_ON_DUPLICATE_REG_ID:将基于注册 id 的现有 Device(创建)转换为更新。有关详细信息,请参阅下文 更新具有重复注册 ID 的设备

  • UNIQUE_REG_ID:强制所有设备模型上的 registration_id 字段为唯一。

APNS 设置

  • APNS_CERTIFICATE:APNS证书文件的绝对路径。不支持带密码的证书。如果iOS应用程序是用“发布”标志构建的,则需要使用生产证书,否则使用调试。有关生成APNS PEM文件的更多信息,请参阅APNS PEM文件生成

  • APNS_AUTH_KEY_PATH:APNS签名密钥文件的绝对路径,用于基于令牌的身份验证。如果您使用的是

    .p8

    签名密钥证书,请使用此选项而不是

    APNS_CERTIFICATE

  • APNS_AUTH_KEY_ID:从您的Apple开发者账户获得的10个字符的密钥ID。

  • APNS_TEAM_ID:用于开发iOS公司应用程序的10个字符的团队ID。

  • APNS_TOPIC:远程通知的主题,通常是应用程序的捆绑ID。如果您省略了此标题,并且您的APNs证书未指定多个主题,则APNs服务器使用证书的主题作为默认主题。

  • APNS_USE_ALTERNATIVE_PORT:使用APNS的端口号2197,而不是默认端口号443。

  • APNS_USE_SANDBOX:使用“api.development.push.apple.com”,而不是默认主机“api.push.apple.com”。默认值取决于您的环境的

    DEBUG

    设置:如果

    DEBUG

    为True且您使用生产证书,则应显式将

    APNS_USE_SANDBOX

    设置为False。

FCM/GCM设置

  • FIREBASE_APP:用于发送推送通知的Firebase应用程序实例。如果未提供,应用程序将使用您使用

    firebase_admin.initialize_app()

    实例化的默认应用程序实例。

  • FCM_MAX_RECIPIENTS:每个批量消息中可以包含的最大接收者数量。如果

    registration_ids

    列表大于该数字,则会发送多个批量消息。默认为1000(FCM支持的最多数量)。

WNS设置

  • WNS_PACKAGE_SECURITY_KEY:待办事项

  • WNS_SECRET_KEY:待办事项

WP设置

  • WP_PRIVATE_KEY:私有证书文件的绝对路径:os.path.join(BASE_DIR, “private_key.pem”)

  • WP_CLAIMS:包含默认值的字典,用于向webpush服务发送的子(主题),如果服务需要联系您(发送者),则会使用它。可以是url或mailto,例如{‘sub’:“mailto:development@example.com”}。

  • WP_ERROR_TIMEOUT:WebPush POST的超时时间。(可选)

有关如何配置WebPush的更多信息,请参阅docs/WebPush

发送消息

FCM/GCM和APNS服务具有稍微不同的语义。当使用模型时,应用程序尝试为两者提供一个公共接口。

      from push_notifications.models import APNSDevice, GCMDevice

      device = GCMDevice.objects.get(registration_id=gcm_reg_id)
      # The first argument will be sent as "message" to the intent extras Bundle
      # Retrieve it with intent.getExtras().getString("message")
      device.send_message("You've got mail")
      # If you want to customize, send an extra dict and a None message.
      # the extras dict will be mapped into the intent extras Bundle.
      # For dicts where all values are keys this will be sent as url parameters,
      # but for more complex nested collections the extras dict will be sent via
      # the bulk message api.
      device.send_message(None, extra={"foo": "bar"})
      device.send_message(None, extra={"foo": "bar"}, use_fcm_notifications=False) # Silent message with custom data.

# You may also pass a Firebase message object.
      device.send_message(messaging.Message(
              notification=messaging.Notification(
                      title='Hello World',
                      body='What a beautiful day.'
              ),
      ))
      # If you want to use gcm.send_message directly, you will have to use messaging.Message.

      device = APNSDevice.objects.get(registration_id=apns_token)
      device.send_message("You've got mail") # Alert message may only be sent as text.
      device.send_message(None, badge=5) # No alerts but with badge.
      device.send_message(None, content_available=1, extra={"foo": "bar"}) # Silent message with custom data.
      # alert with title and body.
      device.send_message(message={"title" : "Game Request", "body" : "Bob wants to play poker"}, extra={"foo": "bar"})
      device.send_message("Hello again", thread_id="123", extra={"foo": "bar"}) # set thread-id to allow iOS to merge notifications

Web Push仅接受一个变量(

message

),该变量直接传递给pywebpush。这条消息可以是一个简单的字符串,它将用作您的通知正文,或者它可以包含

pywebpush

支持的任何数据。

简单示例

from push_notifications.models import WebPushDevice

device = WebPushDevice.objects.get(registration_id=wp_reg_id)

device.send_message("You've got mail")

JSON 示例

import json
from push_notifications.models import WebPushDevice

device = WebPushDevice.objects.get(registration_id=wp_reg_id)

title = "Message Received"
message = "You've got mail"
data = json.dumps({"title": title, "message": message})

device.send_message(data)

批量发送消息

from push_notifications.models import APNSDevice, GCMDevice

devices = GCMDevice.objects.filter(user__first_name="James")
devices.send_message("Happy name day!")

批量发送消息利用了 GCM 和 APNS 提供的批量机制。几乎总是比发送单个通知更可取。

还可以将徽章参数作为接受 token 参数的函数传递,以便为每个用户设置不同的徽章值。假设用户模型有一个 get_badge 方法,该方法返回用户的徽章计数

devices.send_message(
        "Happy name day!",
        badge=lambda token: APNSDevice.objects.get(registration_id=token).user.get_badge()
)

Firebase

django-push-notifications 支持 Firebase 云消息 v1。

当使用 FCM 时,django-push-notifications 将自动使用 通知和数据消息格式,以便 Firebase 设备方便地处理。您可能需要检查负载是否满足您的需求,并在 FCM 诊断控制台 中审查您的通知状态。

# Create a FCM device
fcm_device = GCMDevice.objects.create(registration_id="token", user=the_user)

# Send a notification message
fcm_device.send_message("This is a message")

# Send a notification message with additionnal payload
fcm_device.send_message("This is a enriched message", extra={"title": "Notification title", "icon": "icon_ressource"})

# Send a notification message with additionnal payload (alternative syntax)
fcm_device.send_message("This is a enriched message", title="Notification title", badge=6)

# Send a notification message with extra data
fcm_device.send_message("This is a message with data", extra={"other": "content", "misc": "data"})

# Send a notification message with options
fcm_device.send_message("This is a message", time_to_live=3600)

# Send a data message only
fcm_device.send_message(None, extra={"other": "content", "misc": "data"})

幕后,将创建一个 Firebase 消息。您也可以自己创建此消息并将其传递给 send_message 方法。

向主题成员发送 FCM/GCM 消息

FCM/GCM 主题消息允许您的应用服务器向已选择加入特定主题的多个设备发送消息。基于发布/订阅模型,主题消息支持每个应用无限订阅。开发人员可以选择与正则表达式“/topics/[a-zA-Z0-9-_.~%]+”匹配的任何主题名称。注意:发送消息到主题订阅者时必须使用 gcm_send_bulk_message,并将第一个参数设置为除 None 以外的任何值将导致 400 Http 错误。

from push_notifications.gcm import send_message, dict_to_fcm_message

# Create message object from dictonary. You can also directly create a messaging.Message object.
message = dict_to_fcm_message({"body": "Hello members of my_topic!"})
# First param is "None" because no Registration_id is needed, the message will be sent to all devices subscribed to the topic.
send_message(None, message, to="/topics/my_topic")

参考:FCM 文档

异常

  • NotificationError(Exception):所有与通知相关的错误的基础异常。

  • apns.APNSError(NotificationError):发送 APNS 通知时出错。

  • apns.APNSDataOverflow(APNSError):APNS 负载数据超出最大尺寸,无法发送。

Django REST 框架 (DRF) 支持

可用的 ViewSets 包含 APNS 和 GCM 设备的两个权限口味

  • APNSDeviceViewSetGCMDeviceViewSet

    • 权限如设置中指定(默认为 AllowAny,不建议使用)

    • 设备可以不与用户关联而进行注册

  • APNSDeviceAuthorizedViewSetGCMDeviceAuthorizedViewSet

    • 权限为 IsAuthenticated 和自定义权限 IsOwner,这将仅允许 request.user 获取和更新属于该用户的设备

    • 需要用户进行认证,因此所有设备都将与用户关联

在创建 APNSDevice 时,将验证 registration_id 是否为 64 个或 200 个字符的十六进制字符串。自 2016 年以来,设备令牌长度将从 32 字节增加到 100 字节。

可以通过两种方式之一添加路由

from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet, GCMDeviceAuthorizedViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'device/apns', APNSDeviceAuthorizedViewSet)
router.register(r'device/gcm', GCMDeviceAuthorizedViewSet)

urlpatterns = patterns('',
        # URLs will show up at <api_root>/device/apns
        url(r'^', include(router.urls)),
        # ...
)
  • 使用 as_view(指定要包含的视图)

from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet

urlpatterns = patterns('',
        # Only allow creation of devices by authenticated users
        url(r'^device/apns/?$', APNSDeviceAuthorizedViewSet.as_view({'post': 'create'}), name='create_apns_device'),
        # ...
)

具有重复注册 ID 的设备的更新

DRF 视图集强制实施注册 ID 的唯一性。在相同的使用场景中,它可能会导致问题:如果已注册的移动设备更改其用户,则可能会失败注册,因为注册 ID 已经存在。

当选项UPDATE_ON_DUPLICATE_REG_ID设置为True时,则任何具有已存在注册ID的设备创建都将转换为更新。

UPDATE_ON_DUPLICATE_REG_ID仅与DRF兼容。

项目详情


下载文件

下载适用于您的平台文件。如果您不确定选择哪个,请了解有关安装包的更多信息。

源分布

django-push-notifications-3.1.0.tar.gz (54.9 kB 查看散列值)

上传时间

支持