如何不重复自己(干)
How to Don't Repeat Yourself (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))
我在 class NoteListView 的 get func 和 class NoteView 中重复代码。我不知道如何分离这个功能。我用注释标记了重复的行。有什么建议吗?
我会跳过关于不重复自己的强制性笑话,但是根据 Utkbansal 的评论,您可以创建自己的 Mixin class 或创建自己的基础视图,这两个视图都从中派生。即,对象继承。就是说,最简单(我敢说最奇特!)的方法是通过 class 对 PermissionRequiredMixin
:
进行子class
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))
我在我的代码中有两个地方有基本授权。我想把它作为一个功能分开,而不是重复代码。
我的应用程序:
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))
我在 class NoteListView 的 get func 和 class NoteView 中重复代码。我不知道如何分离这个功能。我用注释标记了重复的行。有什么建议吗?
我会跳过关于不重复自己的强制性笑话,但是根据 Utkbansal 的评论,您可以创建自己的 Mixin class 或创建自己的基础视图,这两个视图都从中派生。即,对象继承。就是说,最简单(我敢说最奇特!)的方法是通过 class 对 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))