Python 如何做';不要重复你自己(干)
我在代码中的两个地方有基本授权。我想把它作为一个函数分开,而不是重复代码 我的应用程序:Python 如何做';不要重复你自己(干),python,django,django-views,http-authentication,Python,Django,Django Views,Http Authentication,我在代码中的两个地方有基本授权。我想把它作为一个函数分开,而不是重复代码 我的应用程序: 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 Permi
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中重复代码。我不知道如何分离这个功能。我用注释标记了重复的行。有什么建议吗?我将跳过关于不重复我自己的强制性笑话,但是根据Utkbansal的评论,您可以创建自己的Mixin类,也可以创建自己的基础视图,这两个视图都是从中派生的。i、 对象继承。也就是说,实现这一点最简单(我敢说是最奇特的!)的方法是将
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))
我将跳过关于不重复我自己的强制性笑话,但是在Utkbansal的评论之后,您可以创建自己的Mixin类,也可以创建自己的基础视图,这两个视图都是从中派生的。i、 对象继承。也就是说,实现这一点最简单(我敢说是最奇特的!)的方法是将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))
你可以用一个装饰师,这看起来很容易理解。您似乎已经知道需要将其放入自己的方法中,那么是什么阻止了您呢?这可能是一个不错的选择,但如果a有两个不同的返回呢?当我创建自己的方法时,代码无法正常工作,只需使用自定义的auth实现创建一个mixin类。在你所有的视图中都使用这种混合。你可以使用一个装饰器,这看起来很容易考虑。您似乎已经知道需要将其放入自己的方法中,那么是什么阻止了您呢?这可能是一个不错的选择,但如果a有两个不同的返回呢?当我创建自己的方法时,代码无法正常工作,只需使用自定义的auth实现创建一个mixin类。在所有视图中使用该混合。