我如何在 Django 中实现通知系统

How can i implement Notifications system in django

我创建了一个应用程序,用户可以在其中 post 提出问题并从其他用户那里得到答案。 现在我想实现一个通知系统,以便当用户回答问题时,该问题的作者将收到通知。喜欢社交媒体通知。

主页模板:

<div class="container">
    <div class="row justify-content-center">
        <div class="row justify-content-center">
            <div class="col-md-6">
                <a href="{% url 'question' %}" class="btn btn-primary  m-1">Ask Question</a>
                <a href="{% url 'notification' %}" class="btn btn-primary  m-1">Notifications</a>
                <a href="{% url 'FeedBack' %}" class="btn btn-primary  m-1">FeedBack</a>
                <a href="{% url 'login' %}" class="btn btn-primary  m-1">Log Out</a>
            </div>
        </div>
    </div>
</div>

 <div class="container">
    <div class="row justify-content-center">
        {% for question in list_of_question reversed %}
        <div class="col-md-4">
            <div class="card my-3">
                <div class="card-header">
                    <p class="card-title">{{question.user.username.upper}}</p>
                </div>
                <div class="card-body">
                    <a href="{% url 'view-Question' question.id %}" style="text-decoration: none;">
                        <p class="card-title">{{question.title}}</p>
                    </a>
                    <p>Category: {{question.category}}</p>
                </div>
            </div>
        </div>
        {%endfor%}
    </div>
</div>

模特:

class Question(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100, blank=False, null=False)
    body = RichTextField(blank=False, null=False) 
    category = models.CharField(max_length=50, blank=False, null=False)

    def __str__(self):
        return str(self.title)

class Answer(models.Model):
    user = models.ForeignKey(User, blank=False, null=False, on_delete=models.CASCADE)
    answer = RichTextField(blank=False, null=False)
    post = models.ForeignKey(Question, blank=False, null=False, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.user)

浏览量:

class My_Question(LoginRequiredMixin, CreateView):
    model = Question
    fields = ['title', 'body', 'category']
    template_name = 'question.html'
    success_url = reverse_lazy('index')

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super (My_Question, self).form_valid(form)

class My_Answer(LoginRequiredMixin, CreateView):
    model = Answer
    fields = ['answer']
    template_name = 'answer.html'
    success_url = reverse_lazy('index')

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.post_id = self.kwargs['pk']
        return super (My_Answer, self).form_valid(form)

def viewQuestion(request, pk):
    question = Question.objects.get(id=pk)
    answers = Answer.objects.filter(post_id=question)
    context = {'question':question, 'answers':answers}
    return render(request, 'viewQuestion.html', context)

首页浏览量:

@login_required(login_url='login')
def index(request):
    query = request.GET.get('q', None)
    list_of_question = Question.objects.all()
    if query is not None:
        list_of_question = Question.objects.filter(
            Q(title__icontains=query) |
            Q(category__icontains=query)
        )
    context = {'list_of_question':list_of_question}
    return render(request, 'index.html', context)

网址

path('index/', views.index, name='index'),
path('view/<int:pk>/', views.viewQuestion, name='view-Question'),
path('question/<int:pk>/answer/', views.My_Answer.as_view(), 
name='answer'),
path('question/', views.My_Question.as_view(), name='question'),

这里是 Django 中基本通知系统的大纲:

型号

您需要一个模型来存储通知。每个通知都属于一个用户并具有内容(即文本消息)。您还需要存储消息是否已被阅读和时间戳:

class Notification(models.Model):
    is_read = models.BooleanField(default=False)
    message = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

创建通知

然后您可以在需要时为用户创建新的通知,例如当其他用户回答问题时,您还可以在视图中为问题的所有者创建通知。

class My_Answer(LoginRequiredMixin, CreateView):
    ...
    def form_valid(self, form):
        ...
        form.instance.user = self.request.user
        question_author = form.instance.post.user
        Notification.objects.create(user=question_author, text="New answer!")
        ...
        return super().form_valid(form)

通知列表

那么您需要一个列出当前用户的所有通知的页面。这可以通过标准列表视图来实现。

查询看起来像这样:

class NotificationListView(ListView):
    model = Notification

    def get_queryset(self):
        return Notifications.objects.filter(user=self.request.user).order_by("-timestamp")

您当然还需要为这个新视图定义一个URL 和一个模板。我们将 URL 名称定义为 notifications.

正在向用户显示新通知

最后,您需要通知用户有关新通知的信息。这可以通过检查当前用户有多少未读通知并在网络徽章上显示徽章来完成。这将是索引视图的一部分。

@login_required(login_url='login')
def index(request):
    ...
    unread_notifications = Notification.objects.filter(user=request.user, is_read=False).count()
    context["unread_notifications"] = unread_notifications
    ...

然后在您的主页上,您需要 link 一个显示所有通知的页面和一个显示当前用户有多少未读通知的徽章。像这样:

<a href="{% url "notifications" %}">
  Notifications
  {% if unread_notifications %}  
    <span class="badge bg-secondary">{{ unread_notifications }}</span>
  {% endif %}
</a>

现实生活中的例子

如果您想了解这是如何在实际项目中实现的,这里是 link 一个名为“Alliance Auth”的开源项目,它实现了一个门户网页并具有非常相似的通知架构. link 指向该门户中的通知应用程序:https://gitlab.com/allianceauth/allianceauth/-/tree/master/allianceauth/notifications