2017-01-16 8 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 в ПОЛУЧИТЬ FUNC и в классе NoteView. Я не знаю, как отделить эту функциональность. Я отметил повторяющиеся строки комментариями. Какие-либо предложения?

+0

Вы можете использовать декоратор https://wiki.python.org/moin/PythonDecorators – lapinkoira

+2

Это выглядит довольно легко вынесет. Вы уже, кажется, знаете, что вам нужно поместить его в свой собственный метод, так что останавливает вас? –

+0

Это может быть хорошим вариантом, но что, если у вас есть два разных результата? –

ответ

1

Я пропущу обязательную шутку о том, чтобы не повторять себя, но, следуя комментарию Уткансала, вы можете создать свой собственный класс 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))