Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

python - Function notifies commentor when the poster should get notified

If I comment on the post named "a", then I get a notification saying that I made the comment on "a" but the notification system should notify the user who created post "a".

I have a clue what to do, because I have done something similar (notifying the user who commented when there's a reply to that comment) thanks to some tutorial.

In models.py for notification, I have to send the right notification and connect to it. I'll post my full code, you can see the bottom function for the connecting, and this is the one I'm having problem with.

    from django.conf import settings
    from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
    from django.contrib.contenttypes.models import ContentType
    from django.core.urlresolvers import reverse
    from django.db import models
    from django.contrib.auth.models import User

    from main.models import Post
    from accounts.models import MyProfile
    from .signals import notify
    # Create your models here.

    class NotificationQuerySet(models.query.QuerySet):
        def get_user(self, recipient):
            return self.filter(recipient=recipient)

        def mark_targetless(self, recipient):
            qs = self.unread().get_user(recipient)
            qs_no_target = qs.filter(target_object_id=None)
            if qs_no_target:
                qs_no_target.update(read=True)

        def mark_all_read(self, recipient):
            qs = self.unread().get_user(recipient)
            qs.update(read=True)

        def mark_all_unread(self, recipient):
            qs = self.read().get_user(recipient)
            qs.update(read=False)

        def unread(self):
            return self.filter(read=False)

        def read(self):
            return self.filter(read=True)

        def recent(self):
            return self.unread()[:5]


    class NotificationManager(models.Manager):
        def get_queryset(self):
            return NotificationQuerySet(self.model, using=self._db)

        def all_unread(self, user):
            return self.get_queryset().get_user(user).unread()

        def all_read(self, user):
            return self.get_queryset().get_user(user).read()

        def all_for_user(self, user):
            self.get_queryset().mark_targetless(user)
            return self.get_queryset().get_user(user)


    class Notification(models.Model):
        sender_content_type = models.ForeignKey(ContentType, related_name='nofity_sender')
        sender_object_id = models.PositiveIntegerField()
        sender_object = GenericForeignKey("sender_content_type", "sender_object_id")

        verb = models.CharField(max_length=255)

        action_content_type = models.ForeignKey(ContentType, related_name='notify_action', 
            null=True, blank=True)
        action_object_id = models.PositiveIntegerField(null=True, blank=True)
        action_object = GenericForeignKey("action_content_type", "action_object_id")

        target_content_type = models.ForeignKey(ContentType, related_name='notify_target', 
            null=True, blank=True)
        target_object_id = models.PositiveIntegerField(null=True, blank=True)
        target_object = GenericForeignKey("target_content_type", "target_object_id")

        recipient = models.ForeignKey(settings.AUTH_PROFILE_MODULE, related_name='notifications')
        read = models.BooleanField(default=False)
        timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)

        objects = NotificationManager()



        def __unicode__(self):
            try:
                target_url = self.target_object.get_absolute_url()
            except:
                target_url = None
            context = {
                "sender": self.sender_object,
                "verb": self.verb,
                "action": self.action_object,
                "target": self.target_object,
                "verify_read": reverse("notifications_read", kwargs={"id": self.id}),
                "target_url": target_url,
            }
            if self.target_object:
                if self.action_object and target_url:
                    return "%(sender)s %(verb)s <a href='%(verify_read)s?next=%(target_url)s'>%(target)s</a> with %(action)s" %context
                if self.action_object and not target_url:
                    return "%(sender)s %(verb)s %(target)s with %(action)s" %context
                return "%(sender)s %(verb)s %(target)s" %context
            return "%(sender)s %(verb)s" %context

        @property   
        def get_link(self):
            try:
                target_url = self.target_object.get_absolute_url()
            except:
                target_url = reverse("notifications_all")

            context = {
                "sender": self.sender_object,
                "verb": self.verb,
                "action": self.action_object,
                "target": self.target_object,
                "verify_read": reverse("notifications_read", kwargs={"id": self.id}),
                "target_url": target_url,
            }
            if self.target_object:
                return "<a href='%(verify_read)s?next=%(target_url)s'>%(sender)s %(verb)s %(target)s with %(action)s</a>" %context
            else:
                return "<a href='%(verify_read)s?next=%(target_url)s'>%(sender)s %(verb)s</a>" %context


    def new_notification(sender, **kwargs):
        kwargs.pop('signal', None)
        recipient = kwargs.pop("recipient")
        verb = kwargs.pop("verb")
        affected_users = kwargs.pop('affected_users')

        #super_user_qs = MyProfile.objects.get(user=Post.moderator), 
    ''' this is wrong, It;s what I tried but failed
        if super_user_qs:
             super_user_instance = super_user_qs
             new_note = Notification(
                    recipient=super_user_instance,
                    verb = verb, # smart_text
                    sender_content_type = ContentType.objects.get_for_model(sender),
                    sender_object_id = sender.id,
                    )
             for option in ("target", "action"):
                    obj = kwargs.pop(option, None)
                    if obj is not None:
                        setattr(new_note, "%s_content_type" %option, ContentType.objects.get_for_model(obj))
                        setattr(new_note, "%s_object_id" %option, obj.id)
             new_note.save()

  the below works for notifying commentor who gets reply
  '''    
        if affected_users is not None:
            for u in affected_users:
                if u == sender:
                    pass
                else:
                    new_note = Notification(
                        recipient=recipient,
                        verb = verb, # smart_text
                        sender_content_type = ContentType.objects.get_for_model(sender),
                        sender_object_id = sender.id,
                        )
                    for option in ("target", "action"):
                        try:
                            obj = kwargs[option]
                            if obj is not None:
                                setattr(new_note, "%s_content_type" %option, ContentType.objects.get_for_model(obj))
                                setattr(new_note, "%s_object_id" %option, obj.id)
                        except:
                            pass
                    new_note.save()
        else:
            new_note = Notification(
                recipient=recipient,
                verb = verb, # smart_text
                sender_content_type = ContentType.objects.get_for_model(sender),
                sender_object_id = sender.id,
                )
            for option in ("target", "action"):
                obj = kwargs.pop(option, None)
                if obj is not None:
                    setattr(new_note, "%s_content_type" %option, ContentType.objects.get_for_model(obj))
                    setattr(new_note, "%s_object_id" %option, obj.id)
            new_note.save()


    notify.connect(new_notification)

And then in models.py I have comment and post models. the get_affected_user is the function that's used in comment views.py to notify affected_user I believe. (I followed a tutorial.)

class Comment(models.Model):
    user = models.ForeignKey(MyProfile)
    parent = models.ForeignKey("self", null=True, blank=True)
    post = models.ForeignKey(Post, null=True, blank=True, related_name="commented_post")
    @property 
    def get_origin(self):
        return self.path

    @property
    def get_comment(self):
        return self.text

    @property
    def is_child(self):
        if self.parent is not None:
            return True
        else:
            return False

    def get_children(self):
        if self.is_child:
            return None
        else:
            return Comment.objects.filter(parent=self)

    def get_affected_users(self):
        """ 
        it needs to be a parent and have children, 
        the children, in effect, are the affected users.
        """
        comment_children = self.get_children()
        if comment_children is not None:
            users = []
            for comment in comment_children:
                if comment.user in users:
                    pass
                else:
                    users.append(comment.user)
            return users
        return None



class Post(models.Model):

    title = models.CharField(max_length = 50)
    moderator = models.ForeignKey(User)
    views = models.IntegerField(default=0)

In views.py for comment, the above get_affected_user is used for notifying commentor who gets reply. I thought about using the same function to achieve what I want, but couldn't. So for that I just set get_affected_user to none for now.

def comment_create_view(request):
    if request.method == "POST" and request.user.is_authenticated():
        parent_id = request.POST.get('parent_id')
        post_id = request.POST.get("post_id")
        origin_path = request.POST.get("origin_path")
        try:
            post = Post.objects.get(id=post_id)
        except:
            post = None

        parent_comment = None
        if parent_id is not None:
            try:
                parent_comment = Comment.objects.get(id=parent_id)
            except:
                parent_comment = None

            if parent_comment is not None and parent_comment.post is not None:
                post = parent_comment.post

        form = CommentForm(request.POST)
        if form.is_valid():
            comment_text = form.cleaned_data['comment']
            if parent_comment is not None:
                # parent comments exists
                new_comment = Comment.objects.create_comment(
                    user=MyProfile.objects.get(user=request.user),
                    path=parent_comment.get_origin, 
                    text=comment_text,
                    post = post,
                    parent=parent_comment
                    )
                #affected_users = parent_comment.get_affected_users()
                #print "this is"
                affected_users = parent_comment.get_affected_users()
                notify.send(
                        MyProfile.objects.get(user=request.user), 
                        action=new_comment, 
                        target=parent_comment, 
                        recipient=parent_comment.user,
                        affected_users = affected_users,
                        verb='replied to')
                messages.success(request, "Thank 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

For you to notify the POST owner, it should be sent this way:

recipient = new_comment.post.moderator

instead of

recipient = MyProfile.objects.get(user=request.user) 

This would send the notification to the moderator of the Post.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...