Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

Django e-commerce part20 Login Required Mixin

Login required の機能をmixinに移す。

mixinは、簡単に言うと、他のmodelなどとは独立して機能するclass・functionのこと

Login Required mixin は、staffメンバー、ログインしているユーザーでないと、variationを見れなくするための機能。これをmixinにする理由は、他のviewでも簡単に利用できるようにするため。

products/mixins.py を作成する。

以下のとおり。これは解説が必要。。。

from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
# decoratorsをimportする。

from django.http import Http404

class StaffRequiedMixin(object):
    @classmethod
    def as_view(self, *args, **kwargs):
        view = super(StaffRequiedMixin, self).as_view(*args, **kwargs)
        return staff_member_required(view)

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_staff:
            return super(StaffRequiedMixin, self).dispatch(request, *args, **kwargs)
        else:
            raise Http404

class LoginRequiedMixin(object):
    @classmethod
    def as_view(self, *args, **kwargs):
        view = super(LoginRequiedMixin, self).as_view(*args, **kwargs)
        return login_required(view)

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginRequiedMixin, self).dispatch(request, *args, **kwargs)
  • まず全体として何をしようとしているのかというと、as_view, dispatchというclass based viewに関する関数を上書きさせようとしているのだと考えられる。関数を上書きして、このmixin classを継承したclass based view に、ログイン認証によるページ表示制限機能を持たせる。

  • デコレーションの使い方と動作について。@classmethodは、その関数をクラスメソッドとして定義するためにつける。(クラスメソッドとインスタンスメソッドの違いはこちら )すごくわかりやすい!!

  • 簡単に言うと、classmethodに設定しておくと、class名.メソッドで、直接インスタンスを呼び出せる!!例えば、as_viewメソッドも、class名.as_view で呼び出しOK。

  • その結果、classmethodに設定することによって、urls.py で設定してある、ProductListView.as_view()のところに、上記のmixin が適用されるようになる。

  • 正直、@method_decoratorの所はさっぱりわからん。

クラスベース汎用ビュー — Django 1.4 documentation

公式サイトをそのまま引用すると、

クラスベースビューの全インスタンスをデコレートするには、クラスの定義そのものを デコレートします。クラスの dispatch() メソッドにデコレータを適用することでできます。

クラスメソッドは単なる関数とは違います。メソッドに関数デコレータを適用することは できません。関数デコレータをメソッドデコレータに変換する必要があります。 method_decorator デコレータは関数デコレータをメソッドデコレータに変換する ので、これをインスタンスメソッドで使えます。

とのこと。つまり 1. @method_decoratorには、関数デコレーターをメソッドデコレーターに変換することができる 2. login_requiredは関数デコレーターのため、@method_decoratorでメソッドデコレーターに変換する 3. dispatch()に、login_required(デコレーター)を適用することで、viewを制限することができる

ということかな。うーん、全然わからん。

  • デコレータについては以下のサイトが分かりやすかったです!

note.crohaco.net

難しく考えすぎとのこと。単純に、

対象オブジェクトを差し替える技術

とのこと。

views.py

views.pyの該当viewに挿入する。

...
from .mixins import StaffRequiedMixin
...
class VariationListView(StaffRequiedMixin, ListView):
...
````

### mixins.py
return staff_member_required だと、ログイン失敗時に、adminが開いてしまうので、login_requiredにしておいて、通常のuserのログイン画面を開かせる。

class StaffRequiedMixin(object): ... return login_required(view) ...

### ecommerce2/urls.py
adminのurlを隠しおきたい場合、適当にurls.pyの箇所を変更する。

url(r'^dj/hide/admin/', include(admin.site.urls)),