Django发出信号,要求处理一个简单的用户通知系统

时间:2016-05-08 07:15:05

标签: django django-views django-signals

我正在学习编码并拥有一个实时的Django项目来让我保持积极性。在我的Django应用程序中,用户发表评论,而其他人回复上述评论。

每当用户刷新他们的主页时,我会计算他们是否收到了他们之前留下的评论的任何新回复,并在他们这样做时显示通知。

这不会扩展,因为如果用户留下了大量评论并因此收到大量回复,则计算所花费的时间比不创建内容的 lurkers 要长。我想改善这些内容创作者的体验。

阅读deeper into it,我认为Django信号是要走的路。例如,每次留下新的回复时,我都可以发出post_save()信号,该信号可以被接收并更新用户的通知。通过这种方式,通知会在留下回复时更新 - 这就是应该的方式。

我将不得不重构我的代码,而且我仍然对上面的实现细节感到朦胧。任何人都可以为我提供一个快速的说明性示例,说明如何实现上述目标?它会让我开始。

目前,用户回复处理是在我的views.py form_valid中的CBV的class PublicreplyView(CreateView)方法中处理的。我猜我可以在CBV中包含以下方法吗?

from django.db.models.signals import post_save post_save.connect(form_valid, sender=User)

然后在其他地方我有一个不同的CBV,它会在刷新主页后为每个用户处理通知。我想我需要完全重写那个?就像我说的那样,我在那方面很朦胧。

希望有人指导我如何处理一个说明性的简单例子。谢谢!

P.S。我在Django< 1.8。

1 个答案:

答案 0 :(得分:4)

@Djizeus在评论中给出了很好的轮廓,我将给你一个完整的例子。我会为通知创建单独的模型,并在注释创建时使用post_save信号创建它们。但是,我不会将此代码挂钩以形成有效但在Comment模型上使用post_save信号。这样,您可以更清晰地分离代码。如果您决定拥有,例如移动和桌面上的不同形式,或者如果您决定重构PublicreplyView,您可能不必触摸信号代码。

当您保存评论时,Django已经触发了post_save信号,因此您只需要听取它们并处理它们。为此,请创建signals.py文件:

from django.dispatch import receiver
from django.db.models.signals import post_save
from .models import Comment, Notification

@receiver(post_save, sender=Comment)
def auto_create_notification(sender, instance, created, **kwargs):
    if created:
        # instance holds the new comment (reply), but you also have to fetch
        # original comment and the user who created it
        parent_comment = instance.parent_comment
        parent_user = parent_comment.user            
        Notification.objects.create(user=parent_user,
                                    comment=parent_comment,
                                    type="reply_created")

要挂钩此信号,​​您​​必须创建/编辑另外两个文件。将其添加到您的apps.py:

from django.apps import AppConfig

# change Comment with your app name
class CommentConfig(AppConfig):

    name = 'comment'
    verbose_name = 'Comment'

    def ready(self):
        import comment.signals

将此添加到您的__init__.py

default_app_config = 'comment.apps.CommentConfig'

关于您的首页视图实施,这取决于您在主页上显示的内容。如果仅显示通知,则通知ListView是一个不错的选择。如果你有不同内容的混合,那么我可能会使用TemplateView并获取你必须在其get_context_data()方法中显示的所有内容。