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

 

 

 

posted on 2020-09-18 17:41  adax  阅读(1007)  评论(0编辑  收藏  举报

导航