Python Django:创建通知引擎
我一直在构建一个电子邮件/短信通知引擎。一个人或一个组可以订阅一个对象,如果该对象得到更新,将通过电子邮件/短信通知该人/组该更改 目前,我已按如下方式实施: models.py mixins.py 使用django的ContentType泛型关系,我可以订阅任何对象的个人/组 我想添加使用相同订阅模型创建全局订阅的功能,以便它们都存储在同一个表中。全局订阅不会有它正在跟踪的对象,但当触发特定模型的任何对象时,将发送电子邮件 我无法将订阅模型推广到能够接受模型实例或触发响应的模型 我想要的功能是: 全局订阅 如果模型X的任何对象发生更改,则更新人员/组 对象级订阅 如果更新了特定对象,则更新人员/组 当前的模型/体系结构是我解决这个问题的好方法,还是我应该以不同的方式处理这个问题Python Django:创建通知引擎,python,django,notifications,functional-programming,django-rest-framework,Python,Django,Notifications,Functional Programming,Django Rest Framework,我一直在构建一个电子邮件/短信通知引擎。一个人或一个组可以订阅一个对象,如果该对象得到更新,将通过电子邮件/短信通知该人/组该更改 目前,我已按如下方式实施: models.py mixins.py 使用django的ContentType泛型关系,我可以订阅任何对象的个人/组 我想添加使用相同订阅模型创建全局订阅的功能,以便它们都存储在同一个表中。全局订阅不会有它正在跟踪的对象,但当触发特定模型的任何对象时,将发送电子邮件 我无法将订阅模型推广到能够接受模型实例或触发响应的模型 我想要的功能是
请注意,前端是AngularJs,因此它专门与我们的django api交互。对于任何想找到解决方案的人,我最后做了:
class Subscription(models.Model):
"""
Model for subscribing to object changes.
Can be subscribed to any object or any model type.
Subcriptions:
model - if any object changes of this type that belongs to the company, update
object - if that specific object changes, update
To create:
Either give a content_object or a content_type. Content object is a model instance. Content type is a ContentType (i.e. Study, Product, etc.)
If it is created wrong, will just be lost in database forever (unless you know it's there, then delete it.)
"""
people = models.ManyToManyField(Person)
groups = models.ManyToManyField(Group)
trigger = models.CharField(max_length=50)
APP_LABELS = [apps to limit the available choices]
# for object subscription
# mandatory fields for generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField(null=True)
content_object = GenericForeignKey('content_type', 'object_id')
def save(self, *args, **kwargs):
'''
Save logic to validate the Subscription model. This is run after the native create() method.
'''
# check if no content_object, then content_type must be defined by user
# probably not necessary since it will fail at creation if content_type isn't an instance of a ContentType, but good to double check
if not self.content_object:
if self.content_type.__class__ != ContentType:
if type(self.content_type) == str:
# if content_type is a string designating a model
self.content_type = ContentType.objects.get(model=self.content_type)
else:
# if content_type is a model class
self.content_type = ContentType.objects.get_for_model(Study)
apps = ', '.join(map(str, self.APP_LABELS))
# check if content_type in our defined apps
if self.content_type.app_label not in apps:
raise ValidationError('Please select a content_object or content_type in apps: {0}'.format(apps))
super(Subscription, self).save(*args, **kwargs)
你是如何使用触发器字段的?嗨@schlumpfpirat,不幸的是我不记得我是如何触发的。我已经好几年没有用Django编码了,对不起!我猜它是通过cronjob或系统正在侦听的订阅事件触发的。
class NotificationMixin(object):
def perform_update(self, serializer):
model_name = str.lower(serializer.Meta.model)
old_obj = model.objects.get(id=serializer.data['id'])
obj = serializer.save()
self.notify(model_name, old_obj, obj)
def notify(self, model_name, old_obj, obj):
# All models have a GenericRelation field for reverse searching
subscriptions = Subscription.objects.filter(**{ model_name: obj })
// *rest of logic to iterate over subscriptions and email people/groups
class Subscription(models.Model):
"""
Model for subscribing to object changes.
Can be subscribed to any object or any model type.
Subcriptions:
model - if any object changes of this type that belongs to the company, update
object - if that specific object changes, update
To create:
Either give a content_object or a content_type. Content object is a model instance. Content type is a ContentType (i.e. Study, Product, etc.)
If it is created wrong, will just be lost in database forever (unless you know it's there, then delete it.)
"""
people = models.ManyToManyField(Person)
groups = models.ManyToManyField(Group)
trigger = models.CharField(max_length=50)
APP_LABELS = [apps to limit the available choices]
# for object subscription
# mandatory fields for generic relation
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField(null=True)
content_object = GenericForeignKey('content_type', 'object_id')
def save(self, *args, **kwargs):
'''
Save logic to validate the Subscription model. This is run after the native create() method.
'''
# check if no content_object, then content_type must be defined by user
# probably not necessary since it will fail at creation if content_type isn't an instance of a ContentType, but good to double check
if not self.content_object:
if self.content_type.__class__ != ContentType:
if type(self.content_type) == str:
# if content_type is a string designating a model
self.content_type = ContentType.objects.get(model=self.content_type)
else:
# if content_type is a model class
self.content_type = ContentType.objects.get_for_model(Study)
apps = ', '.join(map(str, self.APP_LABELS))
# check if content_type in our defined apps
if self.content_type.app_label not in apps:
raise ValidationError('Please select a content_object or content_type in apps: {0}'.format(apps))
super(Subscription, self).save(*args, **kwargs)