我们可以在settings.py文件中定义登录,权限,分页,异常等的全局配置,如下所示

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'utils.page.Page',
'DEFAULT_AUTHENTICATION_CLASSES': (
'utils.permissions.AdminAuth',
),
'EXCEPTION_HANDLER': 'utils.custom_exception_handler.custom_exception_handler',
"DEFAULT_RENDERER_CLASSES":('rest_framework.renderers.JSONRenderer',),
'DATETIME_FORMAT': "%Y-%m-%d %H:%M",
# 'DEFAULT_PERMISSION_CLASSES': (
# 'utils.permissions.LoginPermission',
# )
}

也可以在对应的views,viewset中指定对应的class,来覆盖settings.py中的配置。

登录

drf 自己带了一个登录接口,在reset_framework.urls.py 里面,内容如下

urlpatterns = [
url(r'^login/$', views.LoginView.as_view(template_name='rest_framework/login.html'), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
]

其登录的用户是使用的django自己的User模块,登录方式为sessionid,相关信息存储在数据库中,登录的相关逻辑同admin中一致。

有时候,我们需要自己定义自己的登录用户模块,并在登录的时候,将user放到request.user 属性中,于是,我们可以编写自己的用户登录模块(具体的登录处理逻辑这里不做讨论,这里我们只看看怎么将我们的user model放到request.user中)

根据drf官方文档的例子,我们可以写出下面的代码

from django.contrib.auth.models import User
from rest_framework import authentication
from rest_framework import exceptions class ExampleAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
"""获取META中的信息(也可以通过sessionid,token等在redis or mysql中查找),然后在model中取相应的用户,取出来,则返回对应的对象,没有,则返回None或则raise异常信息。返回的user对象会加载到requst的user属性,如果没有,则使用匿名用户"""
username = request.META.get('X_USERNAME')
if not username:
return None try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise exceptions.AuthenticationFailed('No such user') return (user, None)

可以发现,这一部分的工作仅仅是添加request.user属性,并没有对登录做权限的验证。

权限 permission

主要用于对接口权限的控制,比如知否具有该model,object的权限,是否登录,登录用户是否admin等限制条件。drf自带的权限验证有AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, DjangoModelPermissions, DjangoModelPermissionsOrAnonReadOnly, DjangoObjectPermissions。我们也可以根据自己需要自己定义所需的权限验证类,如下

class Permission(permissions.BasePermission):

    def has_permission(self, request, view):
# docs文档接口不需要权限,因为真的online环境中没有docs的路由
if "docs" in request.path:
return True if getattr(request, "admin_login", None):
"""后台用户验证是否有权限"""
from precontract.views import CageView, PrecontractView, FosterView
from pet.views import PetView, ShapView, PetCategoryView # 根据view的类型,判断所需的权限名字
if isinstance(view, CageView) or isinstance(view, FosterView):
authority_name = "foster"
elif isinstance(view, PrecontractView):
authority_name = "precontract"
elif isinstance(view, PetView):
authority_name = "memeber"
else:
authority_name = "precontract" try:
user = request.user # 自己定义的user model
role = user.role
authority = Authority.objects.get(role=role, state='1')
authority_info = authority.get_info()
if authority_info[authority_name] != '1':
# 判断是否具有权限,返回False,则最终返回403状态,
# 而这里需要我们自定义处理的结果,所以raise一个自己写的异常
# return False
raise RightDenied
# 权限通过,返回True
return True
except BaseException:
raise RightDenied
# return False
raise PermissionDenied

异常处理

我们可以自己定义我们程序的异常的处理返回,或添加额外的返回信息,示例如下

import traceback
from rest_framework.views import exception_handler
from rest_framework.response import Response from django.http import HttpResponseRedirect import logging logger = logging.getLogger('views') def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# response = None # Now add the HTTP status code to the response.
# 捕获程序中的断言异常,作相关的处理,
if response is not None:
# raise exc
response.data['status_code'] = response.status_code
response.data['error'] = str(exc)
elif isinstance(exc, AssertionError):
# 断言错误,
response.data[‘detail’] = "断言错误"
response.data['error'] = str(exc)
else:
raise exc
return response

分页

示例如下

class CustomPagination(pagination.PageNumberPagination):
page_size = 20 # 默认分页大小
page_size_query_param = 'page_size' # 分页大小控制
max_page_size = 30 def get_paginated_response(self, data):
# 自定义分页后的数据返回格式
return Response({
'links': {
'next': self.get_next_link(),
'previous': self.get_previous_link()
},
'count': self.page.paginator.count,
'results': data
})

最新文章

  1. Salesforce Apex 开发环境设置和Hello World示例
  2. http
  3. Emacs 16进制模式
  4. RabbitMQ(五)
  5. HDELETE
  6. error: unknown field 'ioctl' specified in initializer
  7. ASP.NET Web API 2 对 CORS 的支持
  8. mongodb 新建用户 -摘自网络
  9. Android资源管理框架(Asset Manager)简要介绍和学习计划
  10. jquery中DOM的操作方法
  11. 201521123053 <<Java基本语法与类库>>第二周
  12. hi3531的h264压缩中修改波特率
  13. selenium各版本jar包下载地址
  14. linux使用storcli64查看硬盘信息
  15. 构建stm32最小系统板注意事项
  16. D Cloud of Hashtags Codeforces Round #401 (Div. 2)
  17. swift4.2 打印devicetoken
  18. SQL注入之PHP-MySQL实现手工注入-字符型
  19. C#编程(十六)----------匿名类型
  20. Python:数组、队列及堆栈的使用(list用法)--转

热门文章

  1. 如何优化VMWare虚拟机的运行速度(转)
  2. CentOS安装nginx方法命令教程
  3. Linux CentOS如何汉化系统
  4. html网页访问WebAPI中的方法遇到的问题
  5. linux下查看磁盘分区的文件系统格式
  6. Scope_Pre_Post
  7. windows server 2008 64位MySQL5.6免安装版本配置说明
  8. oracle-2_dblink的创建和使用
  9. ORACLE_ALIAS
  10. Spring中<context:annotation-config/>的作用