2017-07-09 10 views
1

私はdjango 1.10を使用してウェブサイトを構築しています。私がログインしていないユーザーのためのページビュー数を制限するためのミドルウェアクラスを書かれている。私は別のアプリケーションのpagerestrict "django - このカスタムミドルウェアが動作しないのはなぜですか?

settings.py [関連エントリ]に、この機能を実装し

# Application definition 

    INSTALLED_APPS = [ 
     'django.contrib.admin', 
     'django.contrib.auth', 
     'django.contrib.contenttypes', 
     'django.contrib.sessions', 
     'django.contrib.messages', 
     'django.contrib.staticfiles', 

     'django.contrib.sites', 

     'pagerestrict.apps.PagerestrictConfig', 
     # ... 
    ] 

    MIDDLEWARE = [ 
     'django.middleware.security.SecurityMiddleware', 
     'django.contrib.sessions.middleware.SessionMiddleware', 
     'django.middleware.common.CommonMiddleware', 
     'django.middleware.csrf.CsrfViewMiddleware', 
     'django.contrib.auth.middleware.AuthenticationMiddleware', 
     'django.contrib.messages.middleware.MessageMiddleware', 
     'django.middleware.clickjacking.XFrameOptionsMiddleware', 

     'pagerestrict.middleware.CheckPageAccessMiddleware',  
    ] 

ミドルウェアコード(middleware.py):

from django.http import HttpResponseRedirect 
from decouple import config 

class CheckPageAccessMiddleware(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     return self.get_response(request) 

    def process_request(self, request): 
     if not request.user.is_authenticated(): 
      current_page_url = request.path_info.lstrip('/') 

      ignore_list = config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')]) 

      #if not current_page_url or not any(current_page_url != url for url in ignore_list): 
      if not current_page_url in ignore_list: 
       # first things first ... 
       if not has_attr(request, 'pages_visited'): 
        request.pages_visited = set() 

       if not has_attr(request, 'page_count'): 
        request.page_count = 0 

       if current_page_url not in request.pages_visited: 
        request.pages_visited.add(current_page_url) 

       request.page_count += 1 

       if request.page_count > config('PAGE_RESTRICT_PAGE_LIMIT'): 
        return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL')) 
私は何回か私のホームページに行くと、ブラウザをリフレッシュすることでこれをテストした

- コードがトリガーされたことはありませんでした。私は何が欠けていますか?

答えて

1

私はついにこれを動作させました。これは、現在無効なStack Overflow DocumentationサイトのMiddlewareトピックに基づいています。 (帰属詳細はcontributor pageで見つけることができるリファレンストピックID:1721)

from django.http import HttpResponseRedirect 
from decouple import config 

class CheckPageAccessMiddleware(object): 
    def __init__(self, next_layer=None): 
     """We allow next_layer to be None because old-style middlewares 
     won't accept any argument. 
     """ 
     self.get_response = next_layer 

    def process_request(self, request): 
     """Let's handle old-style request processing here, as usual.""" 
     # Do something with request 
     # Probably return None 
     # Or return an HttpResponse in some cases 
     if not request.user.is_authenticated(): 
      current_page_url = request.path_info.lstrip('/') 
      print ('Current page url: {0}'.format(current_page_url)) 

      root_url = '' # root url == ('') 
      restrict_redirect_page = config('PAGE_RESTRICT_REDIRECT_URL')[1:] # chop of leading '/' 
      ignore_list = [root_url, restrict_redirect_page] + \ 
       config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')]) 
      print('ignore list: %s' % ",".join([x for x in ignore_list])) 

      #if not current_page_url or not any(current_page_url != url for url in ignore_list): 
      if not current_page_url in ignore_list: 
       # first things first ... 
       if 'pages_visited' not in request.session: 
        request.session['pages_visited'] = '' 

       if 'page_count' not in request.session: 
        request.session['page_count'] = 0 

       pages_visited = [x.strip() for x in request.session['pages_visited'].split(',')] 
       if current_page_url not in pages_visited: 
        pages_visited.append(current_page_url) 
        request.session['pages_visited'] = ",".join(x.strip() for x in pages_visited) 

       request.session['page_count'] += 1 

       print('Request page count: {0}'.format(request.session['page_count'])) 

       if request.session['page_count'] > config('PAGE_RESTRICT_PAGE_LIMIT', cast=int): 
        return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL')) 

     return None 


    def process_response(self, request, response): 
     """Let's handle old-style response processing here, as usual.""" 
     # Do something with response, possibly using request. 
     return response 


    def __call__(self, request): 
     """Handle new-style middleware here.""" 
     response = self.process_request(request) 
     if response is None: 
      # If process_request returned None, we must call the next middleware or 
      # the view. Note that here, we are sure that self.get_response is not 
      # None because this method is executed only in new-style middlewares. 
      response = self.get_response(request) 

     response = self.process_response(request, response) 
     return response 
3

新スタイルのミドルウェアは、デフォルトでprocess_requestprocess_responseを呼び出しません。これは機能的にに渡される__call__get_response関数に置き換えられました。

__call__の中にprocess_request()を呼び出して、Noneでなければ戻り値を処理する必要があります。これを行う最も簡単な方法は、Djangoが提供するMiddlewareMixinを使用することです。これにより、必要な__init____call__のメソッドが定義され、__call__が定義されている場合はprocess_request()process_response()が呼び出されます。

from django.utils.deprecation import MiddlewareMixin 


class CheckPageAccessMiddleware(MiddlewareMixin): 
    def process_request(self, request): 
     if not request.user.is_authenticated(): 
      current_page_url = request.path_info.lstrip('/') 

      ignore_list = config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')]) 

      #if not current_page_url or not any(current_page_url != url for url in ignore_list): 
      if not current_page_url in ignore_list: 
       # first things first ... 
       if not has_attr(request, 'pages_visited'): 
        request.pages_visited = set() 

       if not has_attr(request, 'page_count'): 
        request.page_count = 0 

       if current_page_url not in request.pages_visited: 
        request.pages_visited.add(current_page_url) 

       request.page_count += 1 

       if request.page_count > config('PAGE_RESTRICT_PAGE_LIMIT'): 
        return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL')) 
+0

感謝を。しかし、問題は解決されません - ** N **回以上のページ(http:// localhost:8000/foobar)を更新することができ、ミドルウェアは起動していないようです。 print文を 'process_request()'に置いても、コンソール、ブラウザ、またはdjangoのログファイルには何も印字されないので、暗闇の中を完全に飛んでいます。 –

+0

@HomunculusReticulli私はまだ間違っている可能性のある明白な何も表示されません。サーバーを再起動しましたか? Djangoは正しい設定ファイルを使用していますか? – knbk

+0

はいサーバーを再起動します。とにかくミドルウェアクラスのprintステートメントをコンソールに(またはその場所のどこにでも)印刷するようにしますか? - 少なくとも、私は何が起こっているのか把握する機会があります。現時点では、私はそれが全く呼び出されていないと思う。 –

0

あなたはこのようにインポートを変更することができます。あなたの入力のための try: from django.utils.deprecation import MiddlewareMixin except ImportError: MiddlewareMixin = object

関連する問題