开发者

What's the best way excluding a query set from a queryset

开发者 https://www.devze.com 2023-04-12 14:48 出处:网络
I\'m writing an inbox view and I want to exclude unseen messages from seen messages. My code is : def render_notifications(request):

I'm writing an inbox view and I want to exclude unseen messages from seen messages. My code is :

def render_notifications(request):

 unseen_notices = notification.Notice.objects.filter(recipient=request.user,unseen=True).order_by("-added")
 notices = notification.Notice.objects.filter(recipient=request.user).exclude(id__in = [i.id for i in unseen_notices]).order_by("-added")

 for msg in unseen_notices:
     msg.unseen = False
     msg.save()

 context = RequestContext(request,{'notices':notices,
                'unseen_notices':unseen_notices})
 return render_to_response('my_notifications.html',context_instance=context)

As you can see I exclude all unseen messages using a for loop which doesn't seem convenient and I'm not sure but does this line cause performance issues ? And lastly is there a way that I can replace this line with something similar to :

notices = notification.Notice.objects.filter(recipient=request.user).exclude(id__in =unseen_messages)

Edit:

I can't get seen 开发者_如何学Pythonmessages correctly with using unseen = False , because I mark all unseen messages as seen when the page is visited. With a strange reason when I use unseen = False in notices query, all marked unseen messages are retrieved from notices query.


Django querysets are lazy. This explains why the 'unseen' notices appear in the seen notices list when you follow Derek's suggestion the comments above. The notices query is not executed until the template is rendered when you call render_to_response. By this timetime you have already saved the msg as seen.

If you call list() on your querysets, they are evaluated immediately, and the 'unseen' notifications will no longer appear in the seen notices.

def render_notifications(request):
    user_notices = notification.Notice.objects.filter(recipient=request.user).order_by(-'added')
    unseen_notices = list(user_notices.filter(unseen=True))
    notices = list(user_notices.filter(unseen=False))
    <snip>

An alternative is to render the response, then update the unseen flag on the notifications, then finally return the response.

def render_notifications(request):
    user_notices = notification.Notice.objects.filter(recipient=request.user).order_by(-'added')
    unseen_notices = user_notices.filter(unseen=True)
    notices = user_notices.filter(unseen=False)

    context = RequestContext(request,{'notices':notices,
            'unseen_notices':unseen_notices})
    response = render_to_response('my_notifications.html',context_instance=context)

    # update the seen flag
    unseen_notices.update(unseen=False)

    return response

Note that I've used update method of the queryset instead of looping through each notice. You can't do this if your model has a custom save method or if you are using written pre/post save hooks.


Seem that you can do something like here:

 user_notices = notification.Notice.objects.filter(recipient=request.user)
 unseen_notices = user_notices.filter(unseen=True).order_by("-added")
 notices = user_notices.exclude(unseen=True).order_by("-added")
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号