簡體   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