如何扩展fcm-django的FCMDevice模型并复用现有设备注册API?
嘿,我来帮你一步步搞定这个需求~ 针对你提到的扩展FCM设备模型、复用现有API,还有FCM注册流程的疑问,我给你整理了详细的方案:
1. 扩展FCMDevice模型添加自定义字段
fcm-django支持两种方式扩展设备模型,你可以根据自己的场景选择:
方式一:直接继承FCMDevice(推荐)
如果还没有自己的设备模型,直接继承官方的FCMDevice类,加上你需要的字段最省事。这样能直接复用FCMDevice的所有原生功能(比如registration_id校验、推送方法)。
在你的app的models.py里写:
from django.db import models from fcm_django.models import FCMDevice from django.contrib.auth import get_user_model User = get_user_model() class CustomFCMDevice(FCMDevice): # 添加你需要的自定义字段 language = models.CharField(max_length=10, blank=True, null=True, help_text="比如zh-CN/en-US") lat = models.FloatField(blank=True, null=True, help_text="纬度") lng = models.FloatField(blank=True, null=True, help_text="经度") app_version = models.CharField(max_length=20, blank=True, null=True, help_text="APP版本号") manufacturer = models.CharField(max_length=50, blank=True, null=True, help_text="设备厂商") class Meta: verbose_name = "自定义FCM设备" verbose_name_plural = "自定义FCM设备"
然后在settings.py里告诉fcm-django用你的自定义模型:
FCM_DJANGO_SETTINGS = { "DEVICE_MODEL": "你的app名称.CustomFCMDevice", # 替换成实际的app名 }
最后执行数据库迁移:
python manage.py makemigrations python manage.py migrate
方式二:用OneToOne关联现有设备模型
如果你已经有一套成熟的设备模型了,不想重构,就给现有模型加个OneToOne字段关联FCMDevice:
from django.db import models from fcm_django.models import FCMDevice from django.contrib.auth import get_user_model User = get_user_model() class MyExistingDevice(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # 你的原有字段 language = models.CharField(max_length=10) lat = models.FloatField() lng = models.FloatField() app_version = models.CharField(max_length=20) manufacturer = models.CharField(max_length=50) # 关联FCMDevice fcm_device = models.OneToOneField(FCMDevice, on_delete=models.CASCADE, blank=True, null=True)
这种方式适合不想动原有模型的场景,但后续调用推送方法需要通过fcm_device关联对象来操作。
2. 复用现有注册/更新设备API添加FCM Registration ID
既然你已经有DRF的设备API了,只需要修改序列化器和视图,把FCM的registration_id和自定义字段加进去就行。
第一步:写自定义序列化器
假设用的是方式一的CustomFCMDevice模型,在serializers.py里:
from rest_framework import serializers from .models import CustomFCMDevice class CustomFCMDeviceSerializer(serializers.ModelSerializer): class Meta: model = CustomFCMDevice # 包含原生字段+你的自定义字段,user设为只读(从当前登录用户自动获取) fields = ['id', 'registration_id', 'type', 'language', 'lat', 'lng', 'app_version', 'manufacturer', 'user'] extra_kwargs = { 'user': {'read_only': True}, 'type': {'required': True} # type是ios/android/web,前端必须传 }
第二步:修改现有视图
把你的设备注册/更新视图改成支持这个序列化器,比如如果是一个用户对应多个设备,就用CreateAPIView+UpdateAPIView;如果一个用户只有一个设备,就用get_or_create逻辑:
from rest_framework import generics, permissions from .models import CustomFCMDevice from .serializers import CustomFCMDeviceSerializer class DeviceRegisterUpdateView(generics.CreateAPIView, generics.UpdateAPIView): queryset = CustomFCMDevice.objects.all() serializer_class = CustomFCMDeviceSerializer permission_classes = [permissions.IsAuthenticated] # 确保只有登录用户能操作 def get_object(self): # 单设备场景:获取当前用户的设备,不存在就创建 obj, _ = CustomFCMDevice.objects.get_or_create(user=self.request.user) return obj def perform_create(self, serializer): # 创建时自动绑定当前用户 serializer.save(user=self.request.user)
这样前端调用你原来的API时,只需要额外传registration_id、type和你的自定义字段,就能完成FCM设备的注册/更新了。
3. 快速理清FCM设备注册流程
其实流程很简单,不用慌:
- 移动端获取Registration ID:iOS/Android app启动时,向FCM服务器请求一个唯一的
registration_id(这个是FCM识别设备的凭证) - 前端调用你的API:把
registration_id、设备类型(ios/android)、还有你需要的语言/位置/版本等字段一起传给你的DRF API - 后端保存数据:你的API把这些信息存入自定义的FCMDevice模型
- 发送推送:之后你可以通过模型查询目标设备(比如按用户、语言、版本筛选),调用fcm-django的
send_message方法发推送
举个推送的例子:
# 给某个用户的所有设备发通知 user_devices = CustomFCMDevice.objects.filter(user=target_user) user_devices.send_message( title="新消息提醒", body="你有一条未读消息", data={"message_id": "123"} # 自定义数据,前端可以解析 ) # 给所有中文语言的设备发推送 cn_devices = CustomFCMDevice.objects.filter(language="zh-CN") cn_devices.send_message(title="中文通知", body="这是一条中文推送")
小提示
- 确保
registration_id唯一:FCMDevice模型已经自带unique约束,不用担心重复保存 - 移动端更新Registration ID:如果app重新安装或者FCM刷新了id,前端要调用你的更新API同步数据库,否则推送会失败
- 位置字段如果是实时的,可以让前端定时上传,或者在用户主动授权后更新
内容的提问来源于stack exchange,提问作者Safari
相关产品推荐
相关产品推荐

