RESTful_framework

Representational State Transfer

Posted by youyue on April 16, 2018

1. CBV

FBV:

    url("index/",index) # index(request)
    url("index/(\d+)",index) # index(request,5)
    url("index/(?P\d<name>\d+)",index)# index(request,name=bender)
    
	def index(request):pass
	
	
CBV:
    url("index/",IndexView.as_view()) 
	
	from django.views import View
	class IndexView(View):
	     def get(self,request):
		     pass
		 def post(self,request):
             pass

2. APIView

from rest_framework.views import APIView

class APIView(View):    
    def as_view():     
        view = super(APIView, cls).as_view(**initkwargs)   #  self.dispatch
        
    def dispatch():
         # 重新封装request
         request = self.initialize_request(request, *args, **kwargs)
         self.request = request
         
        # 初始化操作
        self.initial(request, *args, **kwargs)
            
        if request.method.lower() in self.http_method_names:        
            handler = getattr(self, request.method.lower(),self.http_method_not_allowed)       
            response = handler(request, *args, **kwargs)   # self.get(request, *args, **kwargs)

3. 序列化组件

class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()

    serializer_class = BookSerializers  
from rest_framework import serializers
class PublishSerializers(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = '__all__'

4. 视图

方法一:最原始的方法

from rest_framework import serializers


class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"

class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        bs=BookSerializers(book_list,many=True,context={'request': request})
        return Response(bs.data)


    def post(self,request,*args,**kwargs):
        print(request.data)
        bs=BookSerializers(data=request.data,many=False)
        if bs.is_valid():
            print(bs.validated_data)
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)


class BookDetailViewSet(APIView):

    def get(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,context={'request': request})
        return Response(bs.data)

    def put(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,data=request.data,context={'request': request})
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

方法二:mixin类编写视图

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):

    queryset = Book.objects.all()
    serializer_class = BookSerializers

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)



class BookDetailViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

方法三:使用通用的基于类的视图

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(generics.ListCreateAPIView):

    queryset = Book.objects.all()
    serializer_class = BookSerializers

class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

终极方法:viewsets.ModelViewSet

url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
url(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view({
						                'get': 'retrieve',
						                'put': 'update',
						                'patch': 'partial_update',
						                'delete': 'destroy'}),
						            	name="book_detail"),

视图部分:
class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

5. 认证组件

class Authentication(BaseAuthentication):

    def authenticate(self,request):
        token=request._request.GET.get("token")
        token_obj=UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed("验证失败!")
        return (token_obj.user,token_obj)

6. 权限组件

from rest_framework.permissions import BasePermission
class SVIPPermission(BasePermission):
    message="SVIP才能访问!"
    def has_permission(self, request, view):
        if request.user.user_type==3:
            return True
        return False

7. 频率组件

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle

import time

VISITED_RECORD = {}


class VisitThrottle(BaseThrottle):
    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        print(self.get_ident(request))
        visit_ip = self.get_ident(request)
        ctime = time.time()

        # 第一次访问
        if visit_ip not in VISITED_RECORD:
            VISITED_RECORD[visit_ip] = [ctime]
            return True
        self.history = VISITED_RECORD[visit_ip]  # 当前请求IP的记录列表

        # 第二/三次访问
        if len(VISITED_RECORD[visit_ip]) < 3:
            VISITED_RECORD[visit_ip].insert(0, ctime)
            return True

        if ctime - VISITED_RECORD[visit_ip][-1] > 60:
            VISITED_RECORD[visit_ip].pop()
            VISITED_RECORD[visit_ip].insert(0, ctime)
            print("ok")
            return True
        return False

    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])


class VisitThrottles(SimpleRateThrottle):
    scope = "xxx"

    def get_cache_key(self, request, view):
        return self.get_ident(request)

8. 解析器

from rest_framework.parsers import JSONParser,FormParser
class PublishViewSet(generics.ListCreateAPIView):
    parser_classes = [FormParser,JSONParser]
    queryset = Publish.objects.all()
    serializer_class = PublshSerializers
    def post(self, request, *args, **kwargs):
        print("request.data",request.data)

9. 分页

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination

class PNPagination(PageNumberPagination):
        page_size = 1
        page_query_param = 'page'
        page_size_query_param = "size"
        max_page_size = 5

class BookViewSet(viewsets.ModelViewSet):

    queryset = Book.objects.all()
    serializer_class = BookSerializers
    def list(self,request,*args,**kwargs):

        book_list=Book.objects.all()
        pp=LimitOffsetPagination()
        pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self)
        print(pager_books)
        bs=BookSerializers(pager_books,many=True)

        #return Response(bs.data)
        return pp.get_paginated_response(bs.data)

10. 路由

from django.conf.urls import url, include
from snippets import views
from rest_framework.routers import DefaultRouter

# 创建路由器并注册我们的视图。
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet)
router.register(r'users', views.UserViewSet)

# API URL现在由路由器自动确定。
# 另外,我们还要包含可浏览的API的登录URL。
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

11. 响应器

from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer  # 响应器组件

RESTful API 设计指南