一、restful介绍
restful是一种接口规范,前后端根据这种规范开发相应的接口,提高团队开发效率,尤其用于前后端分离,根据规范前后端开发模块互不影响
二、路由

from rest_framework.routers import SimpleRouter,DefaultRouter

在routers模块下 封装了很多关于路由的方法 , 最基础的BaseRouter类,提供自定制的接口
下面这个方法给提供了自动生成两条带参数的url
router = DefaultRouter() # 注册路由 继承BaseRouter类
router.register('user',UserProfileViewset,base_name='useruinfo')
router.register('menu',MenuProfileViewset,base_name='menuinfo')

生成到view的路由映射

三、view视图
帮助开发者提供了一些类,并在类中提供了多种方法供我们使用,下图是提供的主要的类以及继承关系

类介绍
1.APIView

class Nav(APIView):"""初始化菜单"""permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)authentication_classes = (JSONWebTokenAuthentication,)def get(self,request): content = getMenu(request) if not content: return JsonResponse(data=content, code=200, msg="菜单初始化失败", flag=True) else: return JsonResponse(data=content, code=200, msg="菜单初始化成功", flag=True)

提供get,post,put,patch,delete五种方法
2.GenericAPIView

class IndexView(GenericAPIView):queryset = models.UserInfo.objects.all()serializer_class = UserInfoSerializerlookup_field = 'pk'def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: users = self.filter_queryset(queryset=models.UserInfo.objects.get(pk=pk)) ser = self.get_serializer(instance=users) else: users = self.get_queryset() ser = self.get_serializer(instance=users,many=True) return Response(ser.data)

在GenericAPIView中要重写一些字段和方法,不常用
3.GenericViewSet

class IndexView(GenericViewSet):serializer_class = UserInfoSerializerqueryset = models.UserInfo.objects.all()def create(self,request,*args,**kwargs): passdef list(self,request,*args,**kwargs): # 获取列表数据 users = models.UserInfo.objects.all() ser = UserInfoSerializer(instance=users,many=True) return Response(ser.data)def retrieve(self,request,*args,**kwargs): # 获取单条数据 pk = kwargs.get('pk') users = models.UserInfo.objects.get(pk=pk) ser = UserInfoSerializer(instance=users,many=False) return Response(ser.data)def destroy(self,request,*args,**kwargs): passdef update(self,request,*args,**kwargs): pass def partial_update(self,request,*args,**kwargs): pass

这个类继承了ViewSetMixin, generics.GenericAPIView,其中在ViewSetMixin中会重写as_view()方法,因此可以将URL中的请求方式与视图函数绑定到一起,在urls.py中以键值对的方式存在

from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^hehe/', views.hehe), url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})), url(r'^index/(?P<pk>\d+)/$', views.IndexView.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'})),]

4.ModelViewSet
ModelViewSet继承了四个混入类和一个泛类,将会获得增删改查的所有方法

class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet):"""A viewset that provides default `create()`, `retrieve()`, `update()`,`partial_update()`, `destroy()` and `list()` actions."""pass

四、认证
rest_framework给我们提供了认证的接口,由BaseAuthentication类提供接口,也有一些封装好的认证类
接口函数 authticate 认证成功返回一元组(user,token)分别赋值给request.user 和 request.auth

class Auth(BaseAuthentication):def authenticate(self, request): token = request.query_params.get('token') obj = models.Token.objects.filter(token=token).first() if not obj: raise AuthenticationFailed({'code': 1001, 'error': '认证失败'}) return (obj.user.username, obj)

认证方式有多种,可以使用jwt认证

from rest_framework_jwt.authentication import JSONWebTokenAuthenticationclass UserProfileViewset(custom_viewset_base.CustomViewBase):"""permission_classes,authentication_classes放置顺序不能变"""permission_classes = (IsOwnerOrReadOnly,) authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication)serializer_class = UserProfileSerializerqueryset = User.objects.all()pagination_class = custom_pagination.LargeResultsSetPaginationfilter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)filter_class = UserProfileFiltersearch_fields = ('username', ) # ^以什么开头匹配,=等于匹配 "__all__"ordering_fields = ('username',) # 排序ordering = ('username',) # 排序字段

五、权限
由BasePermission类给提供接口 接口函数为 has_permission 以及 has_object_permission

class BasePermission(object):"""A base class from which all permission classes should inherit."""def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ # 这里写我们的权限逻辑 return Truedef has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ return True

可以重写该方法,来控制访问权限

六、序列化
对queryset序列化以及对请求数据格式验证。
通常继承两个类 Serializer 以及 ModelSerializer
Serializer 序列化的每个字段都要自己写 ModelSerializer 会根据数据库表渲染所有字段

class CourseDetailModelSerializers(serializers.ModelSerializer):title = serializers.CharField(source='course.name')img = serializers.ImageField(source='course.course_img')level = serializers.CharField(source='course.get_level_display')recommends = serializers.SerializerMethodField()chapters = serializers.SerializerMethodField()def get_recommends(self, obj): queryset = obj.recommend_courses.all() return [{'id': row.id, 'title': row.name} for row in queryset]def get_chapters(self, obj): queryset = obj.course.course_chapters.all() return [{'id': row.id, 'name': row.name} for row in queryset]class Meta: model = CourseDetail fields = ['course', 'title', 'img', 'level', 'why_study', 'chapters', 'recommends']

七、分页
自定义分页
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination
from collections import OrderedDict
from rest_framework.response import Response

class LargeResultsSetPagination(PageNumberPagination):
page_size = 10 # 每页默认显示条数
page_size_query_param = "page_size" # 每页显示条数传参字符串
page_query_param = "page" # 显示第几页数据传参
max_page_size = 100 # 最大页码

def get_paginated_response(self, data): code = 200 msg = '查询成功' if not data: code = 200 msg = "数据为空" return Response(OrderedDict([ ('code', code), ('msg', msg), ('flag', True), ('count', self.page.paginator.count), ('next', self.get_next_link()), ('previous', self.get_previous_link()), ('results', data) ]))

在view中引入
pagination_class = LargeResultsSetPagination

八、过滤器
使用django_filters模块

import django_filters

from user.models import *

class UserProfileFilter(django_filters.rest_framework.FilterSet):
"""
过滤用户
"""
#id = django_filters.NumberFilter(field_name="id",lookup_expr="exact") # 精确匹配
username = django_filters.CharFilter(field_name="username",lookup_expr="contains")
#name = django_filters.CharFilter(field_name="name", lookup_expr="contains")
#mobile = django_filters.CharFilter(field_name="mobile", lookup_expr="contains")

class Meta: model = UserProfile fields = ["username"]

view视图应用
filter_class = UserProfileFilter

九、渲染器
默认的两个渲染器,一个是Json的,一个是用浏览器访问rest_framework自带的模板的