I created an app where user’s can post a question and get answers from others users. Now I want to implement a notification system, so that when a user answer a question, the author of that question will receive notification. Like social media notifications.
The home templates:
<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>
the models:
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)
The views:
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)
the home page view:
@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)
the urls
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'),
Advertisement
Answer
Here is an outline for a basic notification system in Django:
Model
You need a model to store notifications. Each notification belongs to a user and has content (i.e. a text message). You also need to store whether a message has been read and a timestamp:
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)
Creating a notification
You can then create a new notification for a user when needed, e.g. when another user answers a question you can also create a notification for the question’s owner in the view.
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)
List of notifications
Then you need a page that lists all notifications for the current user. That can be implemented with a standard list view.
The query would look something like this:
class NotificationListView(ListView): model = Notification def get_queryset(self): return Notifications.objects.filter(user=self.request.user).order_by("-timestamp")
You of course also need to define a URL and a template for this new view. We will define the URL name as notifications
.
Showing new notifications to users
Finally, you need to inform users about new notifications. This can be done by checking how many unread notifications the current user has and showing a badge on the web badge. This would be part of the index view.
@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 ...
Then on your home page you need a link to a page that shows all notifications and a badge that shows how many unread notifications the current user has. Something like this:
<a href="{% url "notifications" %}"> Notifications {% if unread_notifications %} <span class="badge bg-secondary">{{ unread_notifications }}</span> {% endif %} </a>
Real life example
If you want to see how this is implemented in a real project, here is the link to an open source project called “Alliance Auth” that implements a portal web page and has a very similar notification architecture. The link is to the notification app within that portal: https://gitlab.com/allianceauth/allianceauth/-/tree/master/allianceauth/notifications