zoukankan      html  css  js  c++  java
  • rest_framework

    rest_framework 是基于restful 规范 开发的,帮助我们能快速开发符合restful规范的数据接口的一个app,记得在setting.py 的INSTALLED_APPS中进行app注册哦,

     序列化

    一、基础序列化 

    方式一:利用json模块下的dump,进行序列化

    方式二:利用form组件下的model_to_dict方法将model对象转成字典,加入list序列化

    方式三:利用Django原生的serializer进行序列化

     1 # # 序列化
     2 # class Book(APIView):
     3 #     def get(self,request):
     4 #         books = models.Book.objects.all()
     5 # #         # 方式一
     6 # #         # list(books)
     7 # #         # return HttpResponse(json.dumps(books))
     8 # #         # 方式二
     9 # #         # from django.forms.models import model_to_dict
    10 # #         # tem =[]
    11 # #         # for obj in books:
    12 # #         #     print(model_to_dict(obj))
    13 # #         # return HttpResponse(json.dumps(tem))
    14 # #         # 方式三
    15 # #         # from django.core import serializers
    16 # #         # data = serializers.serialize('json',books)
    17 # #         # return HttpResponse(data)
    View Code

    二、rest_framework 序列化

    rest_framework 提供的序列化方法的使用方法和form组件十分类似,在学习的时候可以类比的进行学习。

    序列化用到的相关类的继承关系及作用

     

    rest_framework 提供的序列化方法都在rest_framework.serializers类下;

    1、serializers的使用:先创建一个继承serializers.Serializer序列化类用于对数据的序列化

     1 from rest_framework import serializers
     2 from api import models
     3 
     4 class BookSerializers(serializers.Serializer):
     5     nid = serializers.IntegerField()
     6     name = serializers.CharField()
     7     price = serializers.FloatField()
     8     publisher = serializers.CharField(source="publisher.name")
     9     #author = serializers.CharField(source="author.all")
    10 
    11     author = serializers.SerializerMethodField()  # 多对多取决于get_XXX()返回值
    12 
    13     def get_author(self, obj):
    14         temp = []
    15         for obj in obj.author.all():
    16             temp.append(obj.name)
    17         return temp
    18 
    19 
    20 '''
    21 序列化 BookSerializers(serializer.Serializer)的过程:
    22 temp= []
    23 for obj in books:
    24 temp.append(
    25     'nid':obj.nid
    26     'price':obj.price
    27     'name':obj.name
    28     'publisher':str(obj.publisher) #obj.publisher.name
    29     'authors':get_authors(obj)
    30     )
    31 '''
    serializers.py
    1 class Book(APIView):
    2     def get(self,request):
    3          books = models.Book.objects.all()
    4          bs = serializers.BookSerializers(books,many=True)
    5          return Response(bs.data)       
    View.py

    2、ModelSerializers的使用:

     1 class BookModelSerializer(serializers.ModelSerializer):
     2     class Meta:
     3         model = models.Book
     4         fields = "__all__"  # 默认全部序列化,但是想按照自己的来可以覆盖
     5                                     #还有好像是 fields =("想要序列化的字段","...")
     6 
     7     publisher = serializers.CharField(source="publisher.pk")
     8     author = serializers.SerializerMethodField()  # 多对多取决于get_XXX()返回值
     9     def get_author(self, obj):
    10         temp = []
    11         for obj in obj.author.all():
    12             temp.append(obj.nid)
    13         return temp     
    14 
    15     #def create(self, validated_data):
    16     #   print(validated_data)  
    17     #按自己意愿覆盖时原来的create方法可能不支持需要重写
    serializers.py
     1 class BookViewSet(APIView):
     2     def get(self, request, *args, **kwargs):
     3         book_list = models.Book.objects.all()
     4         # bs = serializers.BookSerializers(book_list, many=True)
     5         bs = serializers.BookModelSerializers(book_list, many=True, context={'request': request})
     6         return Response(bs.data)
     7 
     8     def post(self, request, *args, **kwargs):
     9         # bs = serializers.BookSerializers(data=request.data, many=False)
    10         bs = serializers.BookModelSerializers(data=request.data, many=False)
    11         if bs.is_valid():
    12             print('123465', bs.validated_data)
    13             # bs.save()
    14             return Response(bs.data)
    15         else:
    16             return Response(bs.errors)
    View.py

    3、HyperlinkedIdentityField 超链接序列化:

     1 class BookModelSerializers(serializers.ModelSerializer):
     2     class Meta:
     3         model = models.Book
     4         fields = "__all__"
     5         depth = 0
     6 
     7     publisher = serializers.HyperlinkedIdentityField(
     8         view_name="api:publisher_detail",#命名空间下的路由反向解析
     9         lookup_field="publisher_id",#需要反序列化的ID,放进URL分组里,组成完整URL
    10         lookup_url_kwarg="pk" #URL里面的分组
    11     )
    serializers.py

      4、generics.ListCreateAPIView对请求方法进行封装,使代码变得更加简单简洁

    1 from rest_framework import generics
    2 from api import serializers
    3 from api import models
    4 
    5 class BookViewSet(generics.ListCreateAPIView):#类里已经封装好了请求方法对应要执行的函数
    6     queryset = models.Book.objects.all()
    7     serializer_class = serializers.BookModelSerializers
    View.py

      5、viewsets类下的ModelViewSet进一步对路由封装

    1 from rest_framework.viewsets import ModelViewSet
    2 from rest_framework.response import Response
    3 from api import serializers,models
    4 from rest_framework import serializers
    5 
    6 class BookViewSet(ModelViewSet):
    7     queryset = models.Book.objects.all()
    8     serializer_class = serializers.BookModelSerializers
    View Code
     1 urlpatterns = [
     2     # re_path(r'^home/$',views.Home.as_view()),
     3     re_path(r'books/$', views.BookViewSet.as_view({"get":"list"})),
     4     re_path(r'books/(?P<pk>d+)$', views.BookViewSet.as_view({"get":"retrieve"}), name="book_detail"),
     5 
     6     # re_path(r'books/$', views.BookViewSet.as_view()),
     7     # re_path(r'books/(?P<pk>d+)$', views.BookDtailViewSet.as_view(), name="book_detail"),
     8     re_path(r'publisher/$', views.PublisherViewSet.as_view()),
     9     re_path(r'publisher/(?P<pk>d+)$', views.PublisherDtailViewSet.as_view(), name="publisher_detail"),
    10 ]
    url.py

     认证组件

     rest_framework认证组件的初始化在APIView类下的dispatch()里

    使用方法:

     1 #认证类
     2 class AuthToken():
     3     def authenticate(self,request):
     4         nid = request.GET.get("nid")
     5         name = request._request.GET.get("name",None)
     6         print(name)
     7         user = models.Author.objects.filter(name=name).first()
     8         print(user)
     9         if user:
    10             return user.nid, user.name
    11         else:
    12             raise AuthenticationFailed("认证失败 ")
    13     def authenticate_header(self,request):
    14         pass
    认证类
    1 class PublisherDtailViewSet(APIView):
    2     authentication_classes = [serializers.AuthToken,]#局部设置
    3 
    4     def get(self, request, pk):
    5         print("dididi",request.user)
    6         print("didid",request.auth)
    7         publisher = models.Publisher.objects.filter(pk=pk)
    8         bs = serializers.PublisherModelSerializers(publisher, many=True)
    9         return Response(bs.data)
    View.py

      全局配置源码一解:

      在视图类下寻找authentication_class = [“认证类1”,“认证类2”]认证类列表,如实没有设置,则最终会寻找到APIView 类下的authentication_class = api_settings.DEFAULT_AUTHENTICATION_CLASS 执行 ,进入api_settings发现是APISettings类的实例,传参default=DEFAULT,DEFAULT为rest_framework所有数据的迷人配置,进去执行APISettings类下 __init__()方法,完成__init__()方法后没有发现发现任何有关全局配置的信息,有点萌,但是仔细看发现 APISettings 类下的__getattr__()方法,类的实例方法调用该类没有的属性时会触发次方法,APISettings类下没有DEFAULT_AUTHENTICATION_CLASS 属性,所以在执行authentication_class = api_settings.DEFAULT_AUTHENTICATION_CLASS触发__getattr__(),__getattr__()先去setting.py 文件下寻找REST_FRAMEWORK字典,没有就是{},取出认证类的路径,进行解析,拿到认证类执行。如果想某得是图形忽略认证只需要在视图类下authentication_class = [] ,就会先会被截胡。

    权限组件

    rest_framework认证组件的初始化在APIView类下的dispatch()里

    全局配置和认证类是一样的

    使用方法:

       

     1 # 权限组件用到的权限类
     2 from rest_framework.exceptions import PermissionDenied
     3 
     4 
     5 class SVIPermision():
     6     def has_permission(self,request,*args,**kwargs):
     7         permision_tyle = models.Author.objects.filter(name = request.user).first().permision_tyle
     8         if not permision_tyle:
     9             raise PermissionDenied("你没有权限")
    10         elif permision_tyle == 1:
    11             raise PermissionDenied("你权限不够")
    12         else:
    13             return True
    View Code
    1 class PublisherDtailViewSet(APIView):
    2     authentication_classes = [serializers.AuthToken,]
    3     permission_classes = [serializers.SVIPermision,]
    4     def get(self, request, pk):
    5         print("dididi",request.user)
    6         print("didid",request.auth)
    7         publisher = models.Publisher.objects.filter(pk=pk)
    8         bs = serializers.PublisherModelSerializers(publisher, many=True)
    9         return Response(bs.data)
    View Code

     频率组件

       思想:设置间隔时间能访问的次数,对于匿名用户,获取远程IP,作为本地key,为它创建一个列表key:[],先清理列表中大于间隔时间的元素,计算列表元素个数,小于能访问的次数就将本次访问时间加入列表,否则限制访问。

    对于登录用户则用用户名作为key。强制匿名用户登录是防止恶意访问的一种有效手段,但不可能真正做到限制访问(多账户分段访问)

     1 # 频率组件
     2 import time
     3 
     4 Frequent_user_record = {}
     5 from rest_framework.exceptions import Throttled
     6 
     7 
     8 class Throttles():
     9     def __init__(self):
    10         self.interval = 1 * 5  # 间隔1分钟
    11         self.num = 2  # 可以访问2次
    12         self.history = None
    13         self.now = 0
    14 
    15     def allow_request(self, request, *args, **kwargs):
    16         self.now = time.time()
    17         remote_addr = request._request.META.get("REMOTE_ADDR")
    18         remote_addr_obj = Frequent_user_record.get(remote_addr, None)
    19         if not remote_addr_obj:
    20             Frequent_user_record[remote_addr] = [time.time(), ]
    21             return True
    22         self.history = Frequent_user_record[remote_addr]
    23 
    24         while self.history and time.time() - self.history[-1] > self.interval:
    25             Frequent_user_record[remote_addr].pop()
    26 
    27         if len(self.history) < self.num:
    28             Frequent_user_record[remote_addr].insert(0, self.now)
    29             return True
    30         else:
    31             return False
    32 
    33     def wait(self):
    34         return self.interval - (self.now - self.history[-1])
    View Code
     1 class PublisherDtailViewSet(APIView):
     2     authentication_classes = [serializers.AuthToken,]
     3     # permission_classes = [serializers.SVIPermision,]
     4     throttle_classes = [serializers.Throttles,]
     5     def get(self, request, pk):
     6         # print("dididi",request.user)
     7         # print("didid",request.auth)
     8         publisher = models.Publisher.objects.filter(pk=pk)
     9         bs = serializers.PublisherModelSerializers(publisher, many=True)
    10         return Response(bs.data)
    View Code

     

  • 相关阅读:
    JAVA 打开文件乱码
    单引号和双引号的区别
    global和$GLOBALS[]的区别
    php统计数组元素个数
    PHP5.3x不再支持ereg和eregi
    discuz论坛diy标签
    网页特效过渡功能
    discuz缓存机制
    php数组中删除元素
    speedphp是个不错的框架
  • 原文地址:https://www.cnblogs.com/tiaopixiaonaofu/p/13692503.html
Copyright © 2011-2022 走看看