2017-01-16 100 views
0

我有我的代碼兩個地方基本授權。我想將它作爲一個函數分開,而不是重複代碼。如何不重複自己(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)) 

我重複代碼類NoteListView在GET FUNC和類NoteView。我不知道如何分開這個功能。我標註了重複的評論。有什麼建議麼?

+0

你可以使用一個裝飾https://wiki.python.org/moin/PythonDecorators – lapinkoira

+2

這看起來很容易分解出。你似乎已經知道你需要將其納入自己的方法,那麼阻礙你的是什麼? –

+0

這可能是一個不錯的選擇,但如果有兩種不同的回報呢? –

回答

1

我將跳過對不重複自己,但Utkbansal的評論跟進,你可以創建自己的混合類,或創建從兩種觀點派生自己的基本視圖強制性的笑話。即對象繼承。這就是說,最簡單的(我敢說,奇的!)的方式來做到這一點是通過繼承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))