在基于函数的视图中优化分页(在Django中)

时间:2017-01-08 01:03:55

标签: django django-views django-pagination

在基于类的Django listview中,当一个值分配给paginate_by时,它会确保object_list方法中的get_context_data仅限于只有那个特定页面需要的对象

E.g。 get_queryset可能会返回1000个对象,但如果单个页面要显示20个对象,则object_list中只有{20}个对象可用get_context_data。在处理大型查询集时,这是一个很好的优化。

如何在基于函数的视图中创建相同的行为?在典型的实现中(并且采用上述示例),将评估所有1000个对象,然后在分页中使用。这意味着在这种特殊情况下,CBV明显优于基于功能的视图。基于功能的视图可以提供相同的功能吗?一个说明性的例子会很棒(或者说他们不能解决这类问题)。

这是实际的CBV:

class PostListView(ListView):
    model = Post
    paginate_by = 20
    template_name = "post_list.html"

    def get_queryset(self):
        return all_posts()

    def get_context_data(self, **kwargs):
        context = super(PostListView, self).get_context_data(**kwargs)
        posts = retrieve_posts(context["object_list"]) #retrieves 20 posts
        return context

这是实际的FBV:

def post_list(request, *args, **kwargs):
    form = PostListForm()
    context = {}
    obj_list = all_posts()
    posts = retrieve_posts(obj_list) #retrieves 1000 posts
    paginator = Paginator(posts, 20)
    page = request.GET.get('page', '1')
    try:
        page = paginator.page(page)
    except PageNotAnInteger:
        page = paginator.page(1)
    except EmptyPage:
        page = paginator.page(paginator.num_pages)

retrieve_posts()函数:

def retrieve_posts(post_id_list):
    my_server = redis.Redis(connection_pool=POOL)
    posts = []
    pipeline1 = my_server.pipeline()
    for post_id in post_id_list:
        hash_name="pt:"+str(post_id)
        pipeline1.hgetall(hash_name)
    result1 = pipeline1.execute()
    count = 0
    for hash_obj in result1:
        posts.append(hash_obj)
        count += 1
    return posts

all_posts()函数:

def all_posts():
    my_server = redis.Redis(connection_pool=POOL)
    return my_server.lrange("posts:1000", 0, -1) #list of ids of 1000 posts

两种方法的响应时间差异(通过newrelic):

enter image description here

蓝色部分正在处理视图。

1 个答案:

答案 0 :(得分:2)

请勿使用原始对象列表调用retreive_posts。在分页后使用页面对象列表。

posts = retrieve_posts(page.obj_list)