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

     

  • 相关阅读:
    Html禁止粘贴 复制 剪切
    表单标签
    自构BeanHandler(用BeansUtils)
    spring配置中引入properties
    How Subcontracting Cockpit ME2ON creates SD delivery?
    cascadia code一款很好看的微软字体
    How condition value calculated in sap
    Code in SAP query
    SO Pricing not updated for partial billing items
    Javascript learning
  • 原文地址:https://www.cnblogs.com/tiaopixiaonaofu/p/13692503.html
Copyright © 2011-2022 走看看