【问题标题】:How to implement Notification view in django correctly?如何在 django 中正确实现通知视图?
【发布时间】:2018-08-16 18:34:54
【问题描述】:

我已经在我的索引视图中实现了 Django 通知。但是我有更多的视图,比如创建视图、更新视图、删除视图等。当用户第一次登录我的应用程序时,我会显示通知和链接的数量,但是当用户切换到另一个视图时,通知的数量会变为零。有没有办法在 Django 的每个视图中保留所有通知。这是我的views.py文件

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, })

【问题讨论】:

  • 你能举例说明切换是什么意思吗?你先点击哪个视图,然后点击哪个视图
  • 就像每当我在索引视图中时,我都会收到通知,但每当我切换到其他视图(如报告创建、更新、请求项目)时,就没有通知。我知道我没有在该视图中发送通知,但我想在索引更新后保留所有视图的通知。
  • 您只是从索引视图本身发送通知计数;其他视图不发送。真的,您根本不应该在视图中这样做,而应该在自定义模板标签中这样做。
  • 我知道这一点,但有什么方法可以让我的通知保留在标题中。当另一个视图加载时它不应该改变

标签: python django python-3.x notifications


【解决方案1】:

花哨的网站为此使用 websockets/AJAX。但是,如果您只是希望它在每次页面加载时更新,请使用 Django 上下文处理器。

上下文处理器是每次渲染任何模板时都会运行的函数。访问哪个视图并不重要。上下文处理器可以添加在每个模板中都可用的其他模板变量。

所以,首先编写函数。如果当前用户已登录,此函数将返回包含object_listnotificationcount 的字典,否则返回任何内容。

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(),
    }

现在告诉 django 使用这个处理器。在您的 settings.py 中,找到 TEMPLATES 部分,在 OPTIONS 下,您将看到 context_processors。添加你的,例如:

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',
        ],
    },
},]

就是这样!现在,当用户登录时,您应该每次都在模板中获取变量。如果您希望标题出现在显示这些变量的每个模板中,您应该将标题放在主站点模板中,然后所有其他模板都应该扩展该模板。这样,您就不会重复 100 次标题模板代码...

PS:我再补充一个建议​​。不要直接返回你的变量,而是嵌套它们以避免混淆你的模板命名空间。像这样:

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

然后,在您的模板中,它将如下所示:

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

等等等等……好多了。

【讨论】:

  • 非常感谢,先生,您解决了我上周遇到的问题。
  • @little_birdie,我试图遵循这个答案,但它干扰了登录和注销系统。无论如何,我赞成你的回答。
  • @Mohammed 谢谢,我的回答只解释了如何使用上下文处理器将一些数据放入每个模板上下文中,它没有解释数据的来源......在我的回答中我使用数据库问题中的代码,但这对其他人不起作用,那部分必须由您编写。但是,如果您解释您遇到的问题,我会尽力提供帮助。或者也许发布一个不同的问题来解释你的问题,我会回答......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多