在数据库有数据使用django的filter查询数据,查询结果有时有数据有时没数据的情况及解决办法

 在使用restframework时,出现了查询结果为空的情况,但是数据库和查询条件都正确。具体代码如下,主要逻辑是判断first参数的值是不是‘true’,如果是则查询第一种messages (未读的messages ),如果不是则查询第二种messages(5s间隔内的messages ) ,最后使用序列化组件序列化messages 。

    def list(self, request, *args, **kwargs):
        user = request.user
        user_id = request.GET.get('user_id', '')
        if not user_id:
            return Response({'detail': 'Parameter error'}, status=status.HTTP_400_BAD_REQUEST)
        first = request.GET.get('first', 'true')
        if first == 'true':
            try:
                messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).order_by(
                    'create_time')
            except Message.DoesNotExist:
                return Response({'detail': "Can't find object"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            receive_messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False,
                                                      push=False).order_by('create_time')
            time = datetime.datetime.now() - datetime.timedelta(seconds=5)
            send_messages = Message.objects.filter(receive_user_id=user_id, send_user_id=user.pk,
                                                   create_time__gt=time).order_by('create_time')
            messages = sort_message(receive_messages, send_messages)
        Conversation.objects.filter(user_1_id=user.pk, user_2_id=user_id).update(user_1_state=True)
        Conversation.objects.filter(user_2_id=user.pk, user_1_id=user_id).update(user_2_state=True)
        Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)
        messages_list = self.get_serializer(messages, many=True)
        return Response(messages_list.data, status=status.HTTP_200_OK)

出现了上述情况后我在if-else里和if-else后面加了打印了messages 的语句。最后测试发现在if-else里的messages 有数据,而if-else后面的messages 数据为空。代码如下。

    def list(self, request, *args, **kwargs):
        user = request.user
        user_id = request.GET.get('user_id', '')
        if not user_id:
            return Response({'detail': 'Parameter error'}, status=status.HTTP_400_BAD_REQUEST)
        first = request.GET.get('first', 'true')
        if first == 'true':
            try:
                messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).order_by(
                    'create_time')
                print('messages1', messages)
            except Message.DoesNotExist:
                return Response({'detail': "Can't find object"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            receive_messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False,
                                                      push=False).order_by('create_time')
            time = datetime.datetime.now() - datetime.timedelta(seconds=5)
            send_messages = Message.objects.filter(receive_user_id=user_id, send_user_id=user.pk,
                                                   create_time__gt=time).order_by('create_time')
            messages = sort_message(receive_messages, send_messages)
            print('messages2', messages)
        Conversation.objects.filter(user_1_id=user.pk, user_2_id=user_id).update(user_1_state=True)
        Conversation.objects.filter(user_2_id=user.pk, user_1_id=user_id).update(user_2_state=True)
        Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)
        print('messages3', messages)
        messages_list = self.get_serializer(messages, many=True)
        return Response(messages_list.data, status=status.HTTP_200_OK)

最后,笔者发现在if-else后面的打印之前有一行代码

 Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)

遂想到原因,django的filter是懒查询,就是只有在调用到查询结果时才会执行查询操作,修改代码如下

    def list(self, request, *args, **kwargs):
        user = request.user
        user_id = request.GET.get('user_id', '')
        if not user_id:
            return Response({'detail': 'Parameter error'}, status=status.HTTP_400_BAD_REQUEST)
        first = request.GET.get('first', 'true')
        if first == 'true':
            try:
                messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).order_by(
                    'create_time')
            except Message.DoesNotExist:
                return Response({'detail': "Can't find object"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            receive_messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False,
                                                      push=False).order_by('create_time')
            time = datetime.datetime.now() - datetime.timedelta(seconds=5)
            send_messages = Message.objects.filter(receive_user_id=user_id, send_user_id=user.pk,
                                                   create_time__gt=time).order_by('create_time')
            messages = sort_message(receive_messages, send_messages)
        Conversation.objects.filter(user_1_id=user.pk, user_2_id=user_id).update(user_1_state=True)
        Conversation.objects.filter(user_2_id=user.pk, user_1_id=user_id).update(user_2_state=True)
        messages_list = self.get_serializer(messages, many=True)
        Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)
        return Response(messages_list.data, status=status.HTTP_200_OK)

在更新数据库之前就序列化,但是理论上是这样,实际上不是。最后返回的结果还是空。但是把

 Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)

这行注释掉就一切正常。

最后的最后又想到,在最后一行代码里

 return Response(messages_list.data, status=status.HTTP_200_OK)

的messages_list.data,这里要指出,这个.data是在Serializer类里的被@property装饰的一个方法。再结合传入的messages其实是个可变变量,在修改messages内部的元素时,不会修改messages的地址。所以在messages_list.data时,django会查询更新后的数据,并将新数据传入序列化组件执行.data方法得到序列化结果。

最终修改成如下代码解决了这个问题。

    def list(self, request, *args, **kwargs):
        user = request.user
        user_id = request.GET.get('user_id', '')
        if not user_id:
            return Response({'detail': 'Parameter error'}, status=status.HTTP_400_BAD_REQUEST)
        first = request.GET.get('first', 'true')
        if first == 'true':
            try:
                messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).order_by(
                    'create_time')
            except Message.DoesNotExist:
                return Response({'detail': "Can't find object"}, status=status.HTTP_400_BAD_REQUEST)
        else:
            receive_messages = Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False,
                                                      push=False).order_by('create_time')
            time = datetime.datetime.now() - datetime.timedelta(seconds=5)
            send_messages = Message.objects.filter(receive_user_id=user_id, send_user_id=user.pk,
                                                   create_time__gt=time).order_by('create_time')
            messages = sort_message(receive_messages, send_messages)
        Conversation.objects.filter(user_1_id=user.pk, user_2_id=user_id).update(user_1_state=True)
        Conversation.objects.filter(user_2_id=user.pk, user_1_id=user_id).update(user_2_state=True)
        res = self.get_serializer(messages, many=True).data
        Message.objects.filter(receive_user_id=user.pk, send_user_id=user_id, state=False).update(state=True, push=True)
        return Response(res, status=status.HTTP_200_OK)

主要修改的就是在更新数据库之前,将之前的查询结果序列化并保存起来。

总结:

  • django的filter查询是懒查询
  • 只有执行了Serializer的data方法才会得到序列化结果
  • 列表是可变变量
posted @ 2019-06-25 20:27  Wuliwawa  阅读(838)  评论(0编辑  收藏  举报