2016-06-22 5 views
0
class ProfileContextMixin(generic_base.ContextMixin, generic_view.View): 

    def get_context_data(self, **kwargs): 
     context = super(ProfileContextMixin, self).get_context_data(**kwargs) 
     profile = get_object_or_404(Profile, user__username=self.request.user) 
     context['profile'] = profile 
     return context 

class CourseListView(ProfileContextMixin, generic_view.ListView): 
    model = Course 
    template_name = 'course_list.html' 
    object_list = None 

    def get_queryset(self): 
     profile = self.get_context_data()['profile'] 
     return super(CourseListView, self).get_queryset().filter(creator=profile) 

私は次の2つのクラスベースビューを持っています。 CourseListViewは私が他のビューで毎回profileを得るためにget_context_dataを上書きする必要がないように書いたProfileContextMixinを継承しています。get_querysetからのDjangoクラスベースビューアクセスコンテキストデータ

は今私のCourseListViewに、私は私のget_queryset作品を知っているget_context_data

で検索したものと同じであるcreator引数に基づいて結果をフィルタリングする必要があり、それは、プロファイルを取得するためにget_context_data()を呼び出しますが、これによって私のget_context_dataが2回呼び出され、同じSQLが2回実行されます。

コンテキストに効率的にアクセスできる方法はありますか?

はUPDATE:

ListView方法のフローチャートを読んだ後、私はこれをやってしまったが、それは最善の方法かどうかわかりません。フィードバックは高く評価されます。

object_list = [] 
    context = None 

    def get_context_data(self, **kwargs): 
     return self.context 

    def get_queryset(self): 
     self.context = super(CourseListView, self).get_context_data() 
     profile = self.context['profile'] 
     queryset = super(CourseListView, self).get_queryset() 
     queryset = queryset.filter(creator=profile) 
     self.context['object_list'] = queryset 
     return queryset 

答えて

1

あなたはdispatchのように、上位関数にget_context_dataから抜け出すプロファイルを移動、またはcached_propertyデコレータを使用することができます。この方法では、あなたのプロフィールは_profile議論の引数に格納され、self.profileを2度目に呼び出した後には、getをDBに2回追加しません。

from django.utils.functional import cached_property 

class ProfileContextMixin(generic_base.ContextMixin, generic_view.View): 
    @cached_property 
    def profile(self): 
     return get_object_or_404(Profile, user__username=self.request.user) 

    def get_context_data(self, **kwargs): 
     context = super(ProfileContextMixin, self).get_context_data(**kwargs) 
     context['profile'] = self.profile 
     return context 

class CourseListView(ProfileContextMixin, generic_view.ListView): 
    model = Course 
    template_name = 'course_list.html' 
    object_list = None 

    def get_queryset(self): 
     return super(CourseListView, self).get_queryset().filter(creator=self.profile) 
+0

ありがとう!私は 'cached_property'について読んできましたが、私はそれがビューで使われているのを見ていませんでした。それをビューに入れても安全ですか?あなたが望むなら、どのようにキャッシュされたプロパティを無効にしますか? – Algorithmatic

+2

安全です。クラスインスタンスに格納されます。したがって、ビューが要求を行うたびにビューがインスタンス化されるため、このビューからレスポンスが返されるまでは、ビューから要求があった瞬間からのみ存在します。 '__init__'での代入とほぼ同じですので、他のメソッドでも' self.argument'を呼び出すことができます。しかし、Djangoでは '__init__'でそれをやることはできませんので、彼らはこのメソッドを考え出しました。 –