Django channel или Django signals, какой из них я должен использовать, чтобы позволить пользователю получать уведомление, когда происходит какое-то действие

Я создал приложение, в котором пользователи могут размещать Вопросы и получать Ответы от некоторых пользователей, как мы делаем это в stackoverflow. Я не хочу, чтобы пользователь обновлял страницу, просто дайте ему знать, что кто-то ответил на его вопрос. Я хочу реализовать функции связи между этими пользователями.

Мои модели

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)

Я хочу реализовать функцию Notifications, чтобы когда User отвечает на вопрос, автор этого Question получит уведомление, которое перенаправит его/ее на вопрос, на который кто-то ответил Question, подобно тому, как мы получаем уведомления в stack overflow каждый день на работе.

Я пытаюсь понять каждый из этих методов django channels и django signals, но кажется, что мне нужно больше объяснений и помощи, чтобы внедрить это в мое приложение.

Я пытаюсь реализовать это, используя django signals, поскольку django channels учебники сосредоточены на системе графиков.

я пытаюсь создать новую модель под названием Notification

class Notifications(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    notify = models.ForeignKey(Answer, on_delete=models.CASCADE)

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

и сделать в моих представлениях что-то вроде этого:

def notifications(request, pk):
    answer = Answer.objects.get(id=pk)
    get_notify = Notification.objects.filter(notify=answer)
    return render(request, 'notification.html')

Делать что-то вроде этого кажется более простым способом, но проблема в том, что я не знаю, как уведомить пользователя из шаблона, когда происходит какое-то действие. Пожалуйста, как я могу сделать это в django? Большое спасибо.

Вот набросок базовой системы уведомлений в 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)

Создание уведомления

Затем вы можете создать новое уведомление для пользователя, когда это необходимо, например, когда другой пользователь отвечает на вопрос, вы также можете создать уведомление для владельца вопроса в представлении.

    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_unread=True).count()
    context["unread_notifications"] = unread_notifications
    ...

Затем на главной странице вам нужна ссылка на страницу, которая показывает все уведомления и значок, который показывает, сколько непрочитанных уведомлений у текущего пользователя. Что-то вроде этого:

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

Пример из реальной жизни

Если вы хотите посмотреть, как это реализовано в реальном проекте, вот ссылка на проект с открытым исходным кодом под названием "Alliance Auth", который реализует веб-страницу портала и имеет очень похожую архитектуру уведомлений. Ссылка на приложение для уведомлений внутри этого портала: https://gitlab.com/allianceauth/allianceauth/-/tree/master/allianceauth/notifications

Вернуться на верх