0

I have implemented Django notification in my index view. But I have more view like create a view, update view delete view etc. When the user first login to my application, I show the number of notification and links but when the user switches to another view then number of notification changes to zero. Is there any way to retain all the notification in every view of Django. This is my views.py file

from django.shortcuts import render, redirect, render_to_response
from django.http import HttpResponse, HttpResponseRedirect
from django.views.generic.edit import FormMixin

from .models import Report_item, ClaimForm, UserNotification
from django.views import generic
from django.db.models import Q
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from django.utils import timezone
from django.views.generic import View, UpdateView, DeleteView
from .forms import SignUpForm, LoginForm
from django.contrib.auth import logout

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.core.urlresolvers import reverse_lazy
from django.db.models import Q


def IndexView(request):
    if request.user.is_anonymous:
        print("Hello")
        query_list = Report_item.objects.all()
        query = request.GET.get('q')
        if query:
            query_list = query_list.filter(Q(title__icontains=query) |
                                           Q(item_type__icontains=query) |
                                           Q(city__icontains=query) |
                                           Q(Description__icontains=query)).distinct()
        context = {
            "object_list": query_list,
        }
        return render(request, "feed/index.html", context)
    else:
        query_list = Report_item.objects.all()
        query = request.GET.get('q')
        if query:
            query_list = query_list.filter(Q(title__icontains=query) |
                                           Q(item_type__icontains=query) |
                                           Q(city__icontains=query) |
                                           Q(location__icontains=query) |
                                           Q(Description__icontains=query)).distinct()

        n = UserNotification.objects.filter(user=request.user, viewed=False)
        context = {
            "object_list": query_list,
            'notification': n,
            'count': n.count(),
        }
        return render(request, "feed/index.html", context)


class SearchCtaegoryView(generic.ListView):
    template_name = "feed/index.html"

    def get_queryset(self):
        query_list = Report_item.objects.all()
        slug = self.kwargs.get("slug")
        if slug:
            query_list = query_list.filter(Q(category__icontains=slug) | Q(category__iexact=slug))
        return query_list


class ReportCreate(generic.CreateView):
    model = Report_item
    fields = ['title', 'item_type', 'location', 'city', 'image', 'Description']

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.owner = self.request.user
        self.object.save()
        return FormMixin.form_valid(self, form)


class ReportDetail(generic.DetailView):
    model = Report_item
    template_name = 'feed/detail.html'


class ClaimForm(generic.CreateView):
    model = ClaimForm
    fields = ['Your_name', 'Your_mobile_number', 'Detail_proof']


class SignUpForm(generic.CreateView):
    form_class = SignUpForm
    template_name = "feed/SignUp.html"

    def get(self, request):
        form = self.form_class(None)
        return render(request, self.template_name, {'form': form})

    def post(self, request):

        form = self.form_class(request.POST)
        if form.is_valid():
            print("form valid")
            user = form.save(commit=False)
            username = form.cleaned_data['username']
            password = form.cleaned_data['password1']
            user.set_password(password)
            form.save()
            user = authenticate(username=username, password=password)
            if user is not None:
                if user.is_active:
                    login(request, user)
                    return redirect('feed:index')
        else:
            print(form.errors)

        return render(request, self.template_name, {'form': form})


class LoginForm(generic.CreateView):
    print("login")
    form_class = LoginForm
    template_name = "feed/SignUp.html"

    def get(self, request):
        form = self.form_class(None)
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = self.form_class(request.POST)
        if form.is_valid():
            UserModel = get_user_model()
            email = request.POST['email']
            password = request.POST['password']
            username = UserModel.objects.get(email=email)
            user = authenticate(request, username=username, password=password)
            if user is not None:
                if user.is_active:
                    login(request, user)
                    return redirect('')
        else:
            print(form.errors)


def logout_view(request):
    logout(request)
    query_list = Report_item.objects.all()
    return render(request, "feed/index.html", {'object_list': query_list})


def Profile(request, username):
    print(username)
    qs = Report_item.objects.filter(owner__username=username)
    context = {
        "object_list": qs,
    }
    return render(request, "feed/profile.html", context)


class ReportUpdate(UpdateView):
    model = Report_item
    fields = ['title', 'item_type', 'location', 'city', 'image', 'Description']


class ReportDelete(DeleteView):
    model = Report_item
    success_url = reverse_lazy('feed:index')


class RequestItem(generic.CreateView):
    model = UserNotification
    fields = ['Name', 'Mobile_No', 'Proof']

    def form_valid(self, form):
        print(self.kwargs)

        self.object = form.save(commit=False)
        qs = Report_item.objects.filter(id=self.kwargs.get("pk"))
        self.object.user = qs[0].owner
        self.object.save()
        return HttpResponse("<h1>Hello Friends </h1>")


def show_notification(request, notification_id):
    n = UserNotification.objects.get(id=notification_id)
    context = {
        "n": n,
    }
    n.viewed = True
    n.save()
    return render(request, "feed/notification.html", context)


def read_notification(request, notification_id):
    n = UserNotification.objects.get(id=notification_id)
    n.viewed = True
    n.save()
    return HttpResponse("<h1>Hello Friends chai pee lo</h1>")


def mynotification(request):
    n = UserNotification.objects.filter(user=request.user, viewed=False)
    print(type(n))
    return render_to_response("feed/loggedin.html",
                              {'full_name': request.user.first_name, 'notification': n, })


def read_Notification(request):
    n = UserNotification.objects.filter(user=request.user)
    print(type(n))
    return render_to_response("feed/loggedin.html",
                              {'full_name': request.user.first_name, 'notification': n, })

4
  • can u give an example of what do you mean by switching .Which view you hitted first and then which one Commented Aug 16, 2018 at 18:41
  • Like whenever I am in Index view only then I have the notification but whenever I switch to other views like report create, update, Request Item then there is no notification. I know that I am not sending notification in that view but I want to retain my notification for all the view after it is updated by the index. Commented Aug 16, 2018 at 18:49
  • You're only sending the notification count from the index view itself; the other views don't send it. Really you shouldn't do that in a view at all, but in a custom template tag. Commented Aug 16, 2018 at 18:54
  • I know this but is there any way that my notification remains in the header. It should not change when the another view loaded Commented Aug 16, 2018 at 19:21

1 Answer 1

5

Fancy web sites use websockets/AJAX for this. But if you just want it to update on every page load, use a Django context processor.

A context processor is a function that runs every time any template is rendered.. and it doesn't matter which view is being accessed. The context processor can add additional template variables that are available in every template.

So, first write the function.. this function returns a dictionary containing object_list, notification, and count for the current user if they are logged in, or nothing if they are not.

def notification_context(request):
    # Most of the code below is simply copied from the question, it
    # would be different for different applications.  The important thing
    # is that we have to figure out the values to be placed in the template
    # context.

    # If the user is not logged in, we don't know who they are so we return an empty.
    # dictionary which results in nothing new being added to the template context.
    if request.user.is_anonymous:
        return {}

    # look up the notifications for the current user
    query_list = Report_item.objects.all()
    query = request.GET.get('q', None)
    if query:
        query_list = query_list.filter(
            Q(title__icontains=query) |
            Q(item_type__icontains=query) |
            Q(city__icontains=query) |
            Q(location__icontains=query) | 
            Q(Description__icontains=query)
        ).distinct()

    n = UserNotification.objects.filter(user=request.user, viewed=False)

    # The return value must be a dict, and any values in that dict
    # are added to the template context for all templates.        
    # You might want to use more unique names here, to avoid having these
    # variables clash with variables added by a view.  For example, `count` could easily
    # be used elsewhere.
    return {
        'object_list': query_list,
        'notification': n,
        'count': n.count(),
    }

Now tell django to use this processor. In your settings.py, find the TEMPLATES section, and under OPTIONS, you'll see context_processors. Add yours, eg:

TEMPLATES = [{
    'OPTIONS': {
        'context_processors': [
            'django.template.context_processors.debug',
            'django.template.context_processors.request',
            'django.contrib.auth.context_processors.auth',
            'django.contrib.messages.context_processors.messages',
            # fill in the correct appname.  Also, normally context processor functions go in 
            # context_processors.py, but if you only have one then it doesn't matter much.
            'your_appname.views.notification_context',
        ],
    },
},]

And that's it! Now, when the user is logged in, you should get your variables in the template every time. And if you want your heading to be in every template with these variables displayed, you should place the heading in a master site template and then all your other templates should extend that one. That way, you don't duplicate your heading template code 100 times...

PS: I'll add one more suggestion. Rather than directly returning your variables, nest them to avoid cluttering up your template namespace. Like so:

return { 'notifications': {
        'object_list': query_list,
        'notification': n,
        'count': n.count(),
    }
}

Then, in your template, it will look like this:

{{ notifications.count }}
{{ notifications.query_list }}

Etc etc.. much nicer.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a ton, Sir, you solved my problem in which I was stuck from last week.
@little_birdie, I tried to follow this answer, but it interfered with login and logout system. Anyway, I upvoted your answer.
@Mohammed thanks, my answer only explains how to use a Context Processor to put some data into every template context, it doesn't explain where the data comes from.. in my answer I use the database code from the question, but that won't work for anyone else, that part has to be written by you. But if you explain the problem you are having I'll try to help. Or maybe post a different question explaining your issue and I'll answer it...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.