Rest-framework使用

下载 pip install djangorestframework

(1) APIView (*****)

  流程:  

     from rest_framework.views import APIView
  APIView(view) 继承了view 在原来基础上扩展功能
  APIView中as_view super了viwe中的as_view
  但是 as_viwe中的dispath 用的是 APIview从写的dispath
  在APIview从写的dispath中从新封装request对象 增加了 权限,认证,频率组件

(2) 序列化组件(*****)

  from django.core.serializers import serialize # Django的序列化组件
  from rest_framework import serializers DRF的序列化组件
  定义类使用
  class BookSerializer(serializers.Serializer):
    title = serializers.CharField( max_length=32)
    price =serializers.DecimalField(max_digits=5,decimal_places=2)
  在接口类使用
    a = BookSerializer('查询出所有的书籍',many=Ture) many默认False意思是序列化一个
    return Response(a.data)
  post提交数据
  a=CourseSerializer(data=request.data)
  if a.is_valid(): # 校验
    Book.objects.create(**request.data) 不能使用save
    return Response(a.data) # 序列化数据
  else:
    return Response(a.errors) # 序列化错误信息
  一对多字段
    publish_email=serializers.CharField(max_length=32,source="publish.email")
    添加source字段会显示这个里面的值
  多对多字段
    #authors=serializers.CharField(max_length=32,source="authors.all") 是一个QuerySet不使用
    authors=serializers.SerializerMethodField() 使用这个
    def get_authors(self,obj):
      ret=[]
      for i in obj.authors.all():
        ret.append(i.name)
      return ret
  使用 ModelSerializer
  class BookSerializer(serializers.ModelSerializer):
    class Meta:
    model=Book
    # fields=["title","price"]
    fields="__all__"

    # publish=serializers.CharField(max_length=32,source="publish.name")

    # authors=serializers.SerializerMethodField()
    # def get_authors(self,obj):
    # ret=[]
    # for i in obj.authors.all():
    # ret.append({"name":i.name,"pk":i.pk})
    # return ret
  post提交
    def post(self,request):
    serializer=BookSerializer(data=request.data,many=False)

    if serializer.is_valid():
      serializer.save() # create操作 可以使用
      return Response(serializer.data)
    else:
      return Response(serializer.errors)

  如果我查询1条数据()get)的时候 冲突
  所以在写一个视图类 让get put delete放入

  修改一条数据(put)
  def put(self,request,id):
    edit_obj = Book.objects.get(pk=id)
    serializer=BookSerializer(data=request.data,instance=edit_obj)
    if serializer.is_valid():
      serializer.save() # edit_obj.update(request.data)
      return Response(serializer.data)
    else:
      return Response(serializer.errors)

(3) 视图类(mixin)(*****)

  mixin 混合类

  from rest_framework.mixins import
  ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
  查询                 添加        更新          删除      查询单条
  from rest_framework import generics generics.GenericAPIView使用它调用as_view
  class PublishView(ListModelMixin,CreateModelMixin,generics.GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

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

    def post(self,request, *args, **kwargs):
      return self.create(request, *args, **kwargs)
  在使用单条查询的时候必须写 PK值
    url(r'^publishes/(?P<pk>d+)/', views.SPublishView.as_view()),
  在类中不用写id
    class SPublishView(UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,generics.GenericAPIView):

      queryset = Publish.objects.all()
      serializer_class = PublishSerializer

      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)


  使用generics.ListCreateAPIView 和 generics.RetrieveUpdateDestroyAPIView 进行封装
    class AuthorsView(generics.ListCreateAPIView):
      queryset = Author.objects.all()
      serializer_class = AuthorSerializer


    class SAuthorsView(generics.RetrieveUpdateDestroyAPIView):
      queryset = Author.objects.all()
      serializer_class = AuthorSerializer


  终极封装 ModelViewSet 必须在url的as_view中写入制定参数
    from rest_framework.viewsets import ModelViewSet

    class AuthorsView(ModelViewSet):
      queryset = Author.objects.all()
      serializer_class = AuthorSerializer

    url(r'^authors/$', views.AuthorsView.as_view({"get":"list","post":"create"})),
    url(r'^authors/(?P<pk>d+)/', views.AuthorsView.as_view({"get":"retrieve","delete":"destroy","put":"update"})),

(4) 认证组件

  准备2张表
  class User(models.Model):
    user=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    type=((1,"VIP"),(2,"SVIP"),(3,"SSSVIP"))
    user_type=models.IntegerField(choices=type)

  class UserToken(models.Model):
    user=models.OneToOneField("User")
    token=models.CharField(max_length=128)

  在每次登陆时 如果没有就创建 否则就 更新Token值
  import uuid
  random_str = uuid.uuid4()
  if user:
    UserToken.objects.update_or_create(user=user, defaults={"token": random_str})
    response["user"] = user.user
    response["token"] = random_str

  在接口类中使用 authentication_classes = [UserAuth,]
  from rest_framework.authentication import BaseAuthentication
  from rest_framework.exceptions import AuthenticationFailed
  class UserAuth(BaseAuthentication):
    def authenticate(self,request):
      token=request.query_params.get("token")
      usertoken=UserToken.objects.filter(token=token).first()
      if usertoken:
        return usertoken.user,usertoken.token
      else:
        raise AuthenticationFailed("认证失败!")

 

(5) 权限组件

  判断等级进行判断
  在接口类中使用 permission_classes = [SVIPPermission]

  from rest_framework.permissions import AllowAny
  from rest_framework.permissions import BasePermission
  class SVIPPermission(BasePermission):
    message="您没有访问权限!"
    def has_permission(self,request,view):
    if request.user.user_type >= 2: #判断
      return True
    return False

 

(6) 频率组件

  在接口类中使用 throttle_classes = [VisitThrottle]
  from rest_framework.throttling import BaseThrottle
  class VisitThrottle(BaseThrottle):
    def allow_request(self,request,view):
    """
    限制IP每分钟访问不能超过3次
    :param request:
    :param view:
    :return:
    """
    print(self.get_ident(request)) #拿到IP
    remote_addr = request.META.get('REMOTE_ADDR') #拿到IP
    print("REMOTE_ADDR",remote_addr)
    return False

  可以使用自带的频率控制类
  from rest_framework.throttling import SimpleRateThrottle
  class VisitThrottle(SimpleRateThrottle):
    scope="visit_rate"
    def get_cache_key(self,request, view):
      return self.get_ident(request)

  需要在settings中设置
  REST_FRAMEWORK={
    "DEFAULT_THROTTLE_CLASSES": ("app01.utils.throttle_class.VisitThrottle",),
    "DEFAULT_THROTTLE_RATES": {
      "visit_rate": "10/m",
    },
  }

 

(7) 分页组件

  from rest_framework.pagination import PageNumberPagination

  class MyPageNumberPagination(PageNumberPagination):
    page_size=2 #每页显示多少条
    page_query_param="page_num" # get取到的页面名称 &page_num=1
    page_size_query_param="size" # 临时调整 &size = 3 每页显示3条
    max_page_size=5 # 最大可以临时调整5条

  print(request.user,request.auth)

  book_list=Book.objects.all() # 对所有书分页

  pnp=MyPageNumberPagination() # 分页器对象

  paged_book_list=pnp.paginate_queryset(book_list,request) # 对什么分页

  serializer=BookSerializer(paged_book_list,many=True) # 序列化分页后的数据

 

(8) 解析器组件(*****)

  from rest_framework.parsers import JSONParser,FormParser,FileUploadParser
  在类中设置 parser_classes = [] 自定义格式
  根据客户端发送到后端的数据 是用的json格式还是urlencoded格式
  根据格式服务器根据那种格式解
  发送的请求体格式 a=1&b=2 urlencoded格式 在form表单中entype中设置格式 或
  ajax也是可以用contenttype设置
  发送到服务器我根据什么解格式

 

(9) 响应器组件

  默认支持2种响应
  当浏览器去访问时候返给你一个页面
  用postman发给的是json数据

 

(10) url注册器

  from rest_framework import routers
  router = routers.DefaultRouter()
  router.register("authors",views.AuthorsView) #根据名字 和视图类就可以访问

  放到url中 from django.conf.urls import url,include
  url(r'^', include(router.urls)),

 

原文地址:https://www.cnblogs.com/luchenhui/p/10453505.html