zoukankan      html  css  js  c++  java
  • rest-framework之APIView 序列化组件

    rest-framework之APIView

    一 安装djangorestframework

    方式一:pip3 install djangorestframework

    方式二:pycharm图形化界面安装

    方式三:pycharm命令行下安装(装在当前工程所用的解释器下)

    二 djangorestframework的APIView分析

    • as_view 方法
    	 @classmethod
        def as_view(cls, **initkwargs):
            """
            Store the original class on the view function.
    
            This allows us to discover information about the view when we do URL
            reverse lookups.  Used for breadcrumb generation.
            """
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    raise RuntimeError(
                        'Do not evaluate the `.queryset` attribute directly, '
                        'as the result will be cached and reused between requests. '
                        'Use `.all()` or call `.get_queryset()` instead.'
                    )
                cls.queryset._fetch_all = force_evaluation
    
            view = super(APIView, cls).as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
    
            # Note: session based authentication is explicitly CSRF validated,
            # all other authentication is CSRF exempt.
            return csrf_exempt(view)
    	```
    	
    - dispatch 方法
    ``` python
    	def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                self.initial(request, *args, **kwargs)
    
                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                response = self.handle_exception(exc)
    
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response
    
    	```
    - initialize_request 方法
    ``` python
        def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    	```
    - initial方法(内部调用认证,权限和频率)
      ``` python
      def initial(self, request, *args, **kwargs):
            """
            Runs anything that needs to occur prior to calling the method handler.
            """
            self.format_kwarg = self.get_format_suffix(**kwargs)
      
            # Perform content negotiation and store the accepted info on the request
            neg = self.perform_content_negotiation(request)
            request.accepted_renderer, request.accepted_media_type = neg
      
            # Determine the API version, if versioning is in use.
            version, scheme = self.determine_version(request, *args, **kwargs)
            request.version, request.versioning_scheme = version, scheme
      
            # Ensure that the incoming request is permitted
            self.perform_authentication(request)
            self.check_permissions(request)
            self.check_throttles(request)
    

    三 djangorestframework的Request对象简单介绍

    ![](https://img2018.cnblogs.com/blog/1094724/201811/1094724-20181120144238791-1289781803.png)
    

    序列化组件

    序列化组件之 serializers.Serializer

    1. 导入:
    from rest_framework import serializers
    
    1. 写一个类,(名字任意),继承 serializers.Serializer
      class BookSer(serializers.Serializer):
         nid=serializers.IntegerField()
         name3=serializers.CharField(source='name')
         price=serializers.CharField()
         # publish_date = serializers.DateField()
         publish_date = serializers.CharField()
         # publish=serializers.CharField(source='publish.email')
         publish=serializers.CharField(source='publish.name')
         #指定models内的方法
         xxx=serializers.CharField(source='test')
         # authors=serializers.CharField(source='authors.all')
          
         # SerializerMethodField,可以写一个方法方法名叫:get_字段名字,方法返回值,会赋给authors  固定用法, get_字段名字
         aa=serializers.SerializerMethodField()
         # def get_authors(self,obj):
         #     authors=obj.authors.all()
         #     # ll=[ author.name for author in authors]
         #     ll=[ {'name':author.name,'age':author.age} for author in authors]
         #     return ll
         def get_aa(self, obj):
             authors = obj.authors.all()
             # ll=[ author.name for author in authors]
             #可以继续去关联查询
             ser=AuthorSer(authors,many=True)
             return ser.data
             
      class AuthorSer(serializers.Serializer):
      	id=serializers.IntegerField(source='nid')
      	age=serializers.CharField()
      	name=serializers.CharField()
    

    models

    	class Book(models.Model):
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)
            price = models.DecimalField(max_digits=5, decimal_places=2)
            publish_date = models.DateField(auto_now_add=True)
            publish =models.ForeignKey(to='Publish',
            to_field='nid',
            on_delete=models.CASCADE)
            authors=models.ManyToManyField(to='Author')
            def test(self):
                return 'ttttttt'
            def __str__(self):
                return self.name
    
    1. 如果不指定source,字段名,必须跟数据库列名一致.列名及数据库字段名称
    2. source 既可以指定数据属性,又可以指定方法属性,可以写(publish.name)
    3. 使用:

    1.查询出要序列化的数据: python books = models.Boos.object.all()
    2.ret = myserial.BoosSer(books,many=True) 多条(queryset对象),必须指定many = True
    3.ret = myserial.BoosSer(books,many=False) 多条(queryset对象),必须指定many = False
    6. aa=serializers.SerializerMethodField()

    • 必须配套一个方法(get_aa(self,obj)),方法返回结果,会赋值给aa
    • 在方法内部,可以继续使用序列化组件

    序列化组件之 serializers.ModelSerializer

    • 用户同Serializer

    • 不同点 : serializers.ModelSerializer 可以直接在views save存储.! serializers.Serializer 需要自己去写save方法

        	from rest_framework import serializers
          class BookSer(serializers.ModelSerializer):
      		class Meta:
      			# 指定要序列号的表模型是book
      			model=models.Book
      			#查询所有的列
      			fields='__all__'
                  #也可以传列表,指定取几个
                  #fields=['name','authors','publish']
      			#除了nid都查
      			exclude=['nid']
      			#查询的深度,如果有关联的表,会自动关联查询,深度为1的所有数据
      			depth=1
                  #fields和exclude不能同时用
              	# depth指定深度,个人建议最多用3
      
      

    序列化组件的局部校验 和 全局校验

    • 局部校验 validate_ + '校验字段的名称'
         name=serializers.CharField(error_messages={'required':'该字段必填'})
         def validate_name(self,value):
             if value.startswith('sb'):
                 raise ValidationError('不能以sb开头')
             else:
                 return value
    
    • 全局校验 def validate(self,value)
         def validate(self,value):
             print(type(value))
             print(value)
             name=value.get('name')
             price=value.get('price')
             if name!=price:
                 raise ValidationError('书名和价格不相等')
             else:
        
                 return value
    

    -参考过程-

    from django.shortcuts import render, HttpResponse
    from django.http import JsonResponse
    # Create your views here.
    
    import json
    
    # def books(request):
    #
    #     ll=[{'name':'python全站开发','price':20},{'name':'linux','price':30}]
    #
    #     # return HttpResponse(json.dumps(ll))
    #     return JsonResponse(ll,safe=False,json_dumps_params={'ensure_ascii':False})
    # 原声cbv执行流程---》as_view----》dispatch---》相应到具体的函数
    # from django.views import View
    # class Book(View):
    #     def get(self,reuquest):
    #         # reuquest.method
    #         return HttpResponse('get')
    #     def post(self,request):
    #         return HttpResponse('post')
    
    
    from rest_framework.views import APIView
    
    # class Book(APIView):
    #     def get(self,request):
    #         # 拿原来的request对象
    #         # request._request
    #         # print(request.method)
    #         # print(request._request.method)
    #         # request.POST
    #         # request.method
    #         return HttpResponse('get')
    #     def post(self,request):
    #         print(request.method)
    #         print(request._request.method)
    #         print(request.POST)
    #
    #         # 用apiview之后,再取数据,从request.data
    #         print(request.data)
    #         return HttpResponse('post')
    
    from app01 import models
    # 序列化组建
    # 第一种方式
    # class Book(APIView):
    #     def get(self,request):
    #         response={'status':100,'msg':None}
    #         books=models.Book.objects.all()
    #         # ll=[]
    #         # for book in books:
    #         #     ll.append({'name':book.name,''})
    #         ll=[ {'name':book.name,'price':book.price} for book in books]
    #         response['msg']='查询成功'
    #         response['data']=ll
    #         return JsonResponse(response,safe=False)
    #
    #         # return HttpResponse('get')
    #     def post(self,request):
    #
    #         return HttpResponse('post')
    
    # 第二种方式,用django子自带序列化组件
    from django.core import serializers
    
    
    # class Book(APIView):
    #     def get(self,request):
    #         # response={'status':100,'msg':None}
    #         books = models.Book.objects.all()
    #         ret = serializers.serialize("json", books)
    #         return HttpResponse(ret)
    #
    #         # return HttpResponse('get')
    #     def post(self,request):
    #
    #         return HttpResponse('post')
    
    # 第三种方式。drf的序列化组件
    
    
    class MyResponse():
        def __init__(self):
            self.status = 100
            self.msg = None
    
        @property
        def get_dic(self):
            return self.__dict__
    
    URls
    url(r'^books/$', views.BookView.as_view()),
    url(r'^books/(?P<pk>d+)/', views.BookDetail.as_view()),
        
    # 视图类******
    # 方式一
    # from app01 import myserial
    # class Book(APIView):
    #     queryset=models.Book.objects.all()
    #     serializer_class=myserial.BookSer
    #     def get(self,request):
    #         response=MyResponse()
    #         # 多条
    #         # books = models.Book.objects.all()
    #         # ret=myserial.BookSer(books,many=True)
    #         # 一条
    #         book = self.queryset
    #         # ret = myserial.BookSer(book, many=False)
    #         ret = self.serializer_class(instance=book, many=True)
    #         response.msg='查询成功'
    #         response.data=ret.data
    #         return JsonResponse(response.get_dic,safe=False)
    #
    #         # return HttpResponse('get')
    #     def post(self,request):
    #         # print(request.data)
    #         ser=myserial.BookSer(data=request.data)
    #         if ser.is_valid():
    #             ser.save()
    #             return HttpResponse('成功')
    #         else:
    #             print(ser.errors)
    #
    #             return JsonResponse(ser.errors)
    #
    # class BookDetail(APIView):
    #     def get(self,request,id):
    #         response=MyResponse()
    #         ret=models.Book.objects.filter(pk=id).first()
    #         ser=myserial.BookSer(instance=ret,many=False)
    #         response.msg='查询成功'
    #         response.data=ser.data
    #         return JsonResponse(response.get_dic,safe=False)
    #
    #     def put(self,request,id):
    #         # 修改
    #         response=MyResponse()
    #         book=models.Book.objects.filter(pk=id).first()
    #         ser=myserial.BookSer(instance=book,data=request.data)
    #         if ser.is_valid():
    #             # 可以新增,可以修改
    #             ser.save()
    #             print(ser.data)
    #             print(type(ser.instance))
    #             response.msg='修改成功'
    #             response.data=ser.data
    #
    #         else:
    #             response.msg = '修改失败'
    #             response.status = 101
    #             response.data=ser.errors
    #         return JsonResponse(response.get_dic,safe=False)
    #
    #     def delete(self,request,id):
    #         ret=models.Book.objects.filter(pk=id).delete()
    #         return HttpResponse('删除成功')
    # 方式二
    # from app01 import myserial
    #
    # from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin
    # from rest_framework.generics import GenericAPIView
    #
    # class Book(GenericAPIView,ListModelMixin,CreateModelMixin):
    #     queryset=models.Book.objects.all()
    #     serializer_class=myserial.BookSer
    #     def get(self,request,*args, **kwargs):
    #         return self.list(self,request,*args, **kwargs)
    #
    #         # return HttpResponse('get')
    #     def post(self,request,*args, **kwargs):
    #         return self.create(request,*args, **kwargs)
    #
    # class BookDetail(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    #     queryset=models.Book
    #     serializer_class=myserial.BookSer
    #     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)
    
    
    # class Author(GenericAPIView,ListModelMixin):
    #     queryset=models.Author.objects.all()
    #     serializer_class=myserial.AuthorSer
    #     def get(self,request,*args, **kwargs):
    #         return self.list(self,request,*args, **kwargs)
    
    -----
    
    # 第三种方式
    URLS
    url(r'^books/$', views.BookView.as_view({'get':'list','post':'create'})),
    url(r'^books/(?P<pk>d+)/', views.BookView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
    
    from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
    # class BookView(ListCreateAPIView):
    #     queryset=models.Book.objects.all()
    #     serializer_class=myserial.BookSer
    #
    # class BookDetailView(RetrieveUpdateDestroyAPIView):
    #     queryset=models.Book.objects.all()
    #     serializer_class=myserial.BookSer
    
    ___
    
    # 第四种
    from rest_framework.viewsets import ModelViewSet
    
    # class BookView(ModelViewSet):
    #     queryset=models.Book.objects.all()
    #     serializer_class=myserial.BookSer
    #
    # class AuthorView(ModelViewSet):
    #     queryset=models.Author.objects.all()
    #     serializer_class=myserial.AuthorSer
    
    
    ----
    
    URLS
    url(r'^books/$', views.BookView.as_view({'get':'get_all'})),
    url(r'^books/(?P<pk>d+)/', views.BookView.as_view({'get':'get_one'})),
    
    # 项目中用的最多
    # from rest_framework.viewsets import ViewSetMixin
    # class BookView(ViewSetMixin,APIView):
    #
    #     def get_all(self,request):
    #         return HttpResponse('返回所有')
    #     def get_one(self,request,pk):
    #         return HttpResponse('返回一条')
    
    
    # from app01 import myserial
    # class List():
    #     def list(self,request,*args,**kwargs):
    #         response=MyResponse()
    #         # 多条
    #         # books = models.Book.objects.all()
    #         # ret=myserial.BookSer(books,many=True)
    #         # 一条
    #         book = models.Book.objects.all()
    #         # ret = myserial.BookSer(book, many=False)
    #         ret = self.serializer_class(instance=book, many=True)
    #         response.msg='查询成功'
    #         response.data=ret.data
    #         return JsonResponse(response.get_dic,safe=False)
    #
    
    re_path('students/$', views.Stu.as_view({'get':'get_all'})),
    re_path('students/(?P<pk>d+)/$', views.StuDetail.as_view({'get':'get_one'})),
    
    class Stu(ViewSetMixin,APIView):
    
        def get_all(self,request):
            response = MyResponse()
            strs = models.Student.objects.all()
            ret = myserial.StrSer(instance=strs,many=True)
            response.msg = '查询成功'
            response.data = ret.data
            return JsonResponse(response.get_dic,safe=False)
    
    
    class StuDetail(ViewSetMixin,APIView):
    
        def get_one(self,request,pk):
            response = MyResponse()
            strs = models.Student.objects.filter(pk=pk).first()
            ret = myserial.StrSer(instance=strs,many=False)
            response.msg = '查询成功'
            response.data = ret.data
            return JsonResponse(response.get_dic,safe=False)
    
    
  • 相关阅读:
    利用正则表达式,完成参数的替换
    使用python读取yaml文件
    python+unittet在linux与windows使用的区别
    python发送requests请求时,使用登录的token值,作为下一个接口的请求头信息
    jmeter线程组之间传参
    requests:json请求中中文乱码处理
    ddt源码修改:HtmlTestRunner报告依据接口名显示用例名字
    使用openpyxl的styles,实现写入值时加背景色
    批量数据请求接口
    locust参数化
  • 原文地址:https://www.cnblogs.com/polly-ling/p/9988864.html
Copyright © 2011-2022 走看看