添加对象时的Django分页

时间:2015-10-08 07:49:02

标签: django caching pagination django-cache

我有一个网站,显示总是被添加的照片,人们在主页上的页面之间看到重复(最后添加的照片)

我不完全确定如何处理这个问题,但这基本上是发生了什么:

  • 首页显示最新20张[0:20]
  • 用户滚动(同时将照片添加到数据库
  • 用户加载下一页(通过ajax)
  • 页面显示照片[20:40]
  • 用户看到重复的照片,因为添加到列表顶部的照片会将它们推到下一页

解决此问题的最佳方法是什么?我想我需要以某种方式缓存用户会话上的查询集可能吗?我对缓存知之甚少,所以逐步解释是非常宝贵的

这是获取新页面图像的功能:

def get_images_paginated(query, origins, page_num):
    args = None
    queryset = Image.objects.all().exclude(hidden=True).exclude(tags__isnull=True)
    per_page = 20
    page_num = int(page_num)
    if origins:
        origins = [Q(origin=origin) for origin in origins]
        args = reduce(operator.or_, origins)
        queryset = queryset.filter(args)        


    if query:
        images = watson.filter(queryset, query)
    else:
        images = watson.filter(queryset, query).order_by('-id')
    amount = images.count()
    images = images.prefetch_related('tags')[(per_page*page_num)-per_page:per_page*page_num]

    return images, amount

使用该功能的视图:

def get_images_ajax(request):
    if not request.is_ajax():
        return render(request, 'home.html')

    query = request.POST.get('query')
    origins = request.POST.getlist('origin')
    page_num = request.POST.get('page')

    images, amount = get_images_paginated(query, origins, page_num)
    pages = int(math.ceil(amount / 20))
    if int(page_num) >= pages:
        last_page = True;
    else:
        last_page = False;
    context = {
        'images':images,
        'last_page':last_page,
    }

    return render(request, '_images.html', context)

1 个答案:

答案 0 :(得分:2)

您可以采取的一种方法是在AJAX请求中发送客户端当前拥有的最旧ID(即当前列表中最后一项的ID),然后确保只查询旧ID。

所以get_images_paginated修改如下:

def get_images_paginated(query, origins, page_num, last_id=None):
    args = None
    queryset = Image.objects.all().exclude(hidden=True).exclude(tags__isnull=True)
    if last_id is not None:
        queryset = queryset.filter(id__lt=last_id)
    ...

您需要在AJAX请求中发送最后一个ID,并将其从您的查看功能传递到get_images_paginated

def get_images_ajax(request):
    if not request.is_ajax():
        return render(request, 'home.html')

    query = request.POST.get('query')
    origins = request.POST.getlist('origin')
    page_num = request.POST.get('page')
    # Get last ID. Note you probably need to do some type casting here.
    last_id = request.POST.get('last_id', None)

    images, amount = get_images_paginated(query, origins, page_num, last_id)
    ...

正如@doniyor所说,你应该结合这种逻辑使用Django内置的分页。