2017-01-08 30 views
1

在一类基于Django的listview,当一个下发的一个值paginate_by,它确保object_list提供get_context_data方法局限于只有那些需要的对象该特定页面优化在基于功能的视图(在Django)分页

E.g. get_queryset可能会返回1000个对象,但是如果单个页面显示20个对象,则只有20个对象可用,其中object_list位于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

蓝色部分是视图的处理。

+0

哈桑你好,你似乎有这个看法是正确的。什么似乎是问题? – e4c5

+0

嘿@ e4c5。我检索的对象是redis哈希。在基于类的视图中,上下文被限制为20个对象(感谢'paginate_by'),而在FBV中,我最终执行整个1000个对象列表的检索。因此,与CBV相比,服务器响应时间是我的FBV的两倍。 –

+0

你可以把两个methodos的绝对时间,并张贴retrieve_object_list方法 – e4c5

回答

2

不要用原始对象列表调用retreive_posts。分页后使用页面的对象列表。

posts = retrieve_posts(page.obj_list) 
+0

大事情有小的开始。感谢这个见解。 –

相关问题