2017-01-16 18 views
0

私は自分のコードの2か所で基本的な認可を受けています。私はこれを1つの関数として分離し、コードを繰り返すことはしません。自分自身を繰り返さない方法(DRY)

マイアプリ:

from django.shortcuts import render 
from django.views.generic import View 
from django.http import HttpResponse, Http404 
from django.contrib.auth import authenticate 
from django.core.exceptions import PermissionDenied 
import base64 

from notes.models import Note, load_initial_data 


class NoteListView(View): 



    def filter_queryset(self, query_set): 
     query_params = self.request.GET 
     if 'board' in query_params: 
      query_set = query_set.filter(board=query_params['board']) 
     return query_set 

    def get(self, request): 
     load_initial_data() 
     query_set = self.filter_queryset(Note.objects.all()) 
     basic_auth = True 
     # this lines below ! 
     if basic_auth: 
      if 'HTTP_AUTHORIZATION' in request.META: 
       auth = request.META['HTTP_AUTHORIZATION'].split() 
       if len(auth) == 2: 
        if auth[0].lower() == "basic": 
         uname, passwd = base64.b64decode(auth[1]).split(':') 
         user = authenticate(username=uname, password=passwd) 
         if user is not None and user.is_active: 
          request.user = user 
          if not request.user.is_staff: 
           raise PermissionDenied 
          return HttpResponse(query_set) 

      response = HttpResponse() 
      response.status_code = 401 
      response['WWW-Authenticate'] = 'Basic realm="%s"' % "Basic Auth Protected" 
      return response 
     else: 
      return HttpResponse(query_set) 



class NoteView(View): 

    def get_object(self, obj_id): 
     try: 
      return Note.objects.get(id=int(obj_id)) 
     except IndexError: 
      raise Http404 

    def get(self, request, note_id): 
     load_initial_data() 
     basic_auth = True 
     #this lines below 
     if basic_auth: 
      if 'HTTP_AUTHORIZATION' in request.META: 
       auth = request.META['HTTP_AUTHORIZATION'].split() 
       if len(auth) == 2: 
        if auth[0].lower() == "basic": 
         uname, passwd = base64.b64decode(auth[1]).split(':') 
         user = authenticate(username=uname, password=passwd) 
         if user is not None and user.is_active: 
          request.user = user 

          return HttpResponse(self.get_object(note_id)) 

      response = HttpResponse() 
      response.status_code = 401 
      response['WWW-Authenticate'] = 'Basic realm="%s"' % "Basic Auth Protected" 
      return response 
     else: 
      return HttpResponse(self.get_object(note_id)) 

私は、GET FUNCのクラスNoteListViewで、クラスNoteViewでコードを繰り返します。私はこの機能を分ける方法を知らない。私は繰り返した行にコメントを付けました。助言がありますか?

+0

あなたはこれが出要因は非常に簡単になります – lapinkoira

+2

デコレータhttps://wiki.python.org/moin/PythonDecoratorsを使用することができます。あなたはすでにそれを独自の方法に入れなければならないことを知っているようですので、何があなたを止めていますか? –

+0

これは良い選択ですが、2つの異なるリターンがある場合はどうなりますか? –

答えて

1

自分自身を繰り返さないことについての義務的な冗談はスキップしますが、Utkbansalのコメントをフォローアップすると、独自のMixinクラスを作成することも、両方のビューから派生する独自のベースビューを作成することもできます。すなわち、オブジェクトの継承。これは最も簡単なサブクラス化することでこれを行う方法である(!そして私は、ファンシーあえて言う)、言ったPermissionRequiredMixin

あなたの意見では今
from django.contrib.auth.mixins import PermissionRequiredMixin 

class BasicAuthRequired(PermissionRequiredMixin): 
    def __init__(self): 
     super(BasicAuthRequired, self).__init__() 
     self.basic_auth = True 

    def has_permission(self): 
     if self.basic_auth: 
      if 'HTTP_AUTHORIZATION' not in request.META: 
       return False 
      auth = request.META['HTTP_AUTHORIZATION'].split() 
      if len(auth) != 2 or auth[0].lower() != "basic": 
       return False 
      uname, passwd = base64.b64decode(auth[1]).split(':') 
      user = authenticate(username=uname, password=passwd) 
      if not user or not user.is_active: 
       return False 
      self.request.user = user # from `View` 
      return user.is_staff 
     return True # some other type of auth 

、あなたは私たちは、基本的な認証することを保証することができる場所次の操作を行うだけですることができます検証し、適切に処理し、ちょうど正のケースを処理されています:

class NoteView(BasicAuthRequired, View): 
    def get_object(self, obj_id): 
     try: 
      return Note.objects.get(id=int(obj_id)) 
     except IndexError: 
      raise Http404 

    def get(self, request, note_id): 
     load_initial_data() 
     return HttpResponse(self.get_object(note_id)) 
関連する問題