繁体   English   中英

将 If 语句添加到无法正常工作的信号

[英]Adding If statement to signals not working properly

每当用户喜欢或评论作者收到有关此活动的通知的帖子时,我都会为我的 Django 项目设置通知系统。

我已经阅读了 django 中的信号: https : //docs.djangoproject.com/en/3.1/topics/signals/#listening-to-signals

在帖子模型中,我添加了一个num_likes ,它反映了帖子收到的点num_likes数。

我正在尝试添加一个选项,以便当num_likes达到某个数字时,帖子的作者可以收到通知。 在我的例子中,它是第一个赞。

所以,这是我尝试过的,但什么也没发生。

这是models.py

class Post(models.Model):
    title = models.CharField(max_length=100, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author')
    num_likes = models.IntegerField(default=0, verbose_name='No. of Likes')
    likes = models.ManyToManyField(User, related_name='liked', blank=True)

    def __str__(self):
        return self.title
#---------------------------My trial------------------------------------------
    def like_progress(sender, instance, *args, **kwargs):
        post = instance
        if post.num_likes == 1:
            notify = Notification(post=post, user=post.author, notification_type=3)
            notify.save()

# num_likes
post_save.connect(Post.like_progress, sender=Post)
#---------------------------My trial------------------------------------------

这是通知 model.py

class Notification(models.Model):
    NOTIFICATION_TYPES=((1,'Like'),(2,'Comment'),(3,'Admin'))

    post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name="noti_post", blank=True, null=True)
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="noti_from_user")
    user = models.ForeignKey(User, on_delete=models.CASCADE,related_name="noti_to_user")
    notification_type= models.IntegerField(choices=NOTIFICATION_TYPES)
    text_preview= models.CharField(max_length=90,blank=True)
    date=models.DateTimeField(auto_now=True)
    is_seen=models.BooleanField(default=False)

    def __str__(self):
        return self.notification_type

这是通知应用程序 views.py

def ShowNotifications(request, *args, **kwargs):
    user=request.user
    notifications= Notification.objects.filter(user=user).order_by('-date')
    Notification.objects.filter(user=user, is_seen=False).update(is_seen=True)

    template= loader.get_template('notifications/notifications.html')

    context = {
        'notifications': notifications,
    }

    return HttpResponse(template.render(context, request))

这是 url.py

app_name = 'notifications'

urlpatterns = [
    path('', ShowNotifications, name='show-notifications'),

这是模板:

<!-- Admin Notification -->
{% if notification.notification_type == 3 %}
Your First Like in this post
{% endif %}
<!-- Admin Notification -->

所以总结一下:

我有一个完美运行的通知系统,我只是想在其中添加一个选项,以通知帖子的Author他收到了第一个赞。 我在上面做错了什么,我怎样才能让这个功能工作?

如果有任何模糊或需要更多信息,请询问

由于您的视图中有这两行,您没有收到通知:

notifications= Notification.objects.filter(user=user).order_by('-date')
Notification.objects.filter(user=user, is_seen=False).update(is_seen=True)

让我解释一下这些行中发生了什么。

  1. 您过滤通知,但过滤器 ORM 方法是惰性的,这意味着它不会在需要对象之前执行,在您的情况下是在模板中
  2. 然后更新通知的状态。 与过滤器不同,更新不是惰性的,因此查询会立即执行,并且通知在 DB 中的状态为is_seen为 True。
  3. Django 开始呈现您的模板并执行原始过滤器以检索通知。 此时,数据库中不再有is_seen=False通知,因为您已经在步骤 2 is_seen=True它们更新为is_seen=True 因此,呈现通知的模板中的循环没有显示任何内容,因为它在数据库中找不到任何看不见的通知。

为了缓解这种情况,请将步骤 1 中的通知转换为列表,以便立即执行查询。 通过这种方式,您将一个实际的对象列表传递给您的模板,而不是一个惰性查询集。

这可以解决您的问题:

notifications= list(Notification.objects.filter(user=user).order_by('-date'))

将其转换为列表会强制 Django 立即执行查询并返回对象

在与.models.Post相同的目录中而不是在模型中的新文件like_progress中定义like_progress 这将有助于避免副作用。

在实践中,信号处理程序通常定义在与它们相关的应用程序的信号子模块中。

在 appConfig 中为包含Post模型的应用程序注册信号处理程序,我将应用程序称为“博客”,因此模块路径是blog.apps.BlogConfig并将该模块路径添加到INSTALLED_APPS ,而不仅仅是应用程序名称。

从文档:

信号接收器在应用程序配置类的 ready() 方法中连接。

并查看有关 ready 方法的更多信息

博客应用程序(无论Post模型所在的位置)中的 apps.py 文件应如下所示:

from django.apps import AppConfig
from django.db.models.signals import post_save


class BlogConfig(AppConfig):
    name = 'blog'

    def ready(self):
        from .models import Post
        from .signals import like_progress

        post_save.connect(like_progress, sender=Post)

请注意,导入需要在ready方法中进行。 还有一个选项可以将模型导入指定为字符串。

请记住,在创建通知时还要指定另一个用户作为发件人。 如:

notify = Notification(post=post, user=post.author, sender=liker, notification_type=3)

您可能想查看有关避免重复注册信号处理程序的文档。

这一切都在您链接到的文档中,但它有助于了解 shell ( python manage.py shell ) 中发生的情况。 起初它默默地失败了,但是一旦将信号处理程序移入signals.py 并在appConfig 中注册,它就开始显示一些结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM