在使用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方法才会得到序列化结果
- 列表是可变变量