私信功能的通知处理器

来源:10-15 排错思路讲解与课后作业

Otiose

2021-05-10

老师,我在写本节课后作业中的私信功能的通知时,我把通知处理器写在如下发送私信函数中的倒数第三行:

@login_required
@ajax_required
@require_http_methods(["POST"])
def send_message(request):
    sender = request.user
    recipient_username = request.POST["to"]
    recipient = get_user_model().objects.get(username=recipient_username)
    message = request.POST["message"]
    if len(message.strip()) != 0 and sender != recipient:
        msg = Message.objects.create(
            sender=sender,
            recipient=recipient,
            message=message
        )
        channel_layer = get_channel_layer()
        payload = {
            'type': 'receive',
            'message': render_to_string('messager/single_message.html', {'message': msg}),
            'sender': sender.username
        }
        async_to_sync(channel_layer.group_send)(recipient_username, payload)
        notification_handler(sender, recipient, 'R', msg)
        return render(request, 'messager/single_message.html', {"message": msg})
    return HttpResponse()

但是测试报错:

'action_object': action_object.user.username,
AttributeError: 'Message' object has no attribute 'user'

通知处理器的代码与您后来修复bug后的代码一致:

def notification_handler(actor, recipient, verb, action_object, **kwargs):
    key = kwargs.get('key', 'notification')
    id_value = kwargs.get('id_value', None)
    Notification.objects.create(
        actor=actor,
        recipient=recipient,
        verb=verb,
        action_object=action_object
    )
    channel_layer = get_channel_layer()
    payload = {
        'type': 'receive',
        'key': key,
        'actor_name': actor.username,
        'action_object': action_object.user.username,
        'id_value': id_value
    }
    async_to_sync(channel_layer.group_send)('notifications', payload)

也就是说'action_object': action_object.user.username这行代码走不通,虽然说私信模型类中确实没有user字段,只有sender和recipient。也有可能是我的第四个参数action_object写错了,但是我看了半天确实应该是msg呀,麻烦老师指点一下。

写回答

2回答

请叫我滚去写代码

2021-07-02

私信通知功能代码:

在messager/views.py里的send_message方法里添加一行代码

notification_handler(sender, recipient, 'R', recipient)

添加后如下:

def send_message(request):
    """发送消息,ajax post请求"""

    sender = request.user  # 发送方是当前登陆的用户
    recipient_username = request.POST['to']  # 接收方是前端选择时传过来的参数
    recipient = get_user_model().objects.get(username=recipient_username)  # 查询接收方
    #
    # recipient_pk = request.POST['to']  # 接收方是前端选择时传过来的参数
    # recipient = get_user_model().objects.get(pk=recipient_pk)  # 查询接收方

    message = request.POST['message']  # 消息内容,前端传过来的
    if len(message.strip()) != 0 and sender != recipient:
        # 消息内容去除两端空格后不等于0,且发送者不是接收者(不是自己给自己发)
        msg = Message.objects.create(
            sender=sender,
            recipient=recipient,
            message=message
        )

        channel_layer = get_channel_layer()  # 获取聊天组
        payload = {
            'type': 'receive',  # 这里两个是固定的写法,receive是receive方法
            'message': render_to_string('messager/single_message.html', {'message': msg}),
            'sender': sender.username
        }
        # group_send(group:所在组-接收者的username, message: 消息内容)
        # 因为views.py里是同步,需要使用async_to_sync转为异步发送给consumer
        # print('3*' + recipient_username)
        # print('4*' + slugify(recipient_username))
        # recipient_username 接收方
        async_to_sync(channel_layer.group_send)(slugify(recipient_username), payload)

        # 通知
        notification_handler(sender, recipient, 'R', recipient)

        return render(request, 'messager/single_message.html', {'message': msg})
    return HttpResponse()


第二步:在notifications/views.py修改notification_handler方法添加if判断,修改及添加以下代码

if action_object == recipient:
        action_object_user = recipient.username
    else:
        action_object_user = action_object.user.username

    payload = {
        'type': 'receive',  # 固定写法,指的是consumer.py里的receive方法
        'key': key,
        'id_value': id_value,
        'actor_name': actor.username,
        'action_object': action_object_user
    }

修改完成后的样子:

def notification_handler(actor, recipient, verb, action_object, **kwargs):
    """
    通知处理器
    :param actor:           request.user对象, 前端传过来
    :param recipient:       User Instance 接收者实例,可以是一个或者多个接收者
    :param verb:            str 通知类别
    :param action_object:   Instance 动作对象的实例(比如news, articles, qa)
    :param kwargs:          key, id_value等
    :return:                None
    """

    key = kwargs.get('key', 'notification')
    id_value = kwargs.get('id_value', None)

    # 记录通知的内容,保存数据库s
    Notification.object.create(
        actor=actor,
        recipient=recipient,
        verb=verb,
        action_object=action_object
    )

    channel_layer = get_channel_layer()

    if action_object == recipient:
        action_object_user = recipient.username
    else:
        action_object_user = action_object.user.username

    payload = {
        'type': 'receive',  # 固定写法,指的是consumer.py里的receive方法
        'key': key,
        'id_value': id_value,
        'actor_name': actor.username,
        'action_object': action_object_user
    }




3
0

Jack

2021-05-12

您好,action_object 是对象的作者。如果是文章,就只指文章的作者;如果是问题,就是问题的作者;但,如果是私信的话,就应该是私信的发送者sender

'action_object': action_object.user.username

这个时候上面的就不适用了,因为问题和文章都有user关联,而message只有sender。需要加个判断,改成 action_object.sender.username


0
1
Otiose
老师我按您说的加判断实现功能了,但是测试后发现一个问题就是私信接受者的消息铃铛不会实时亮,只有刷新页面后才会亮,而其他应用的通知功能均正常,请问这是什么原因导致的呢?
2021-05-12
共1条回复

Django高级实战 开发企业级问答网站

融合Django高级用法/算法/设计模式/TestCase测试/云计算打造项目

900 学习 · 756 问题

查看课程