在一類基於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的)的響應時間:
藍色部分是視圖的處理。
哈桑你好,你似乎有這個看法是正確的。什麼似乎是問題? – e4c5
嘿@ e4c5。我檢索的對象是redis哈希。在基於類的視圖中,上下文被限制爲20個對象(感謝'paginate_by'),而在FBV中,我最終執行整個1000個對象列表的檢索。因此,與CBV相比,服務器響應時間是我的FBV的兩倍。 –
你可以把兩個methodos的絕對時間,並張貼retrieve_object_list方法 – e4c5