zoukankan      html  css  js  c++  java
  • rest_frameword框架的基本组件

    序列化

    序列化:转化数据和校验数据(提交数据时校验数据类型)

    开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。

    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey(to="Publish")
        authors=models.ManyToManyField(to="Author")
    
        def __str__(self):
            return self.title
    
    
    class Publish(models.Model):
        name=models.CharField(max_length=32)
        email=models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name=models.CharField(max_length=32)
        age=models.IntegerField()
    
        def __str__(self):
            return self.name
    
    
    class User(models.Model):
        user=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        user_type=models.IntegerField(choices=((1,"普通用户"),(2,"VIP用户"),(3,"SVIP用户")))
    
        def __str__(self):
            return self.user
    
    
    class UserToken(models.Model):
        user=models.OneToOneField(to="User")
        token=models.CharField(max_length=128)
    
        def __str__(self):
            return self.token
    models.py

    1.使用serializers(用法类似与form组件)

    from rest_framework import serializers
    #为Book表定制序列化组件
    #使用Serializer
    class BookSerializers(serializers.Serializer):
      #普通字段 title
    =serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() # 一对多使用Charfiled类型,source更改显示的字段 publish=serializers.CharField(source="publish.email") # 多对多字段 authors=serializers.SerializerMethodField() def get_authors(self,obj):#obj为book对象 temp=[] for author in obj.authors.all(): temp.append({"id":author.id,"name":author.name}) return temp

    2.使用ModelSerializer(使用方法类似与modelform组件)

    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model=Book
            fields="__all__"
            # exclude=["authors",]  #显示authors以外的字段(单独使用)
    
        # authors=serializers.SerializerMethodField()   #可以和fields=“__all__”配合使用
        # def get_authors(self,obj):
        #     temp=[]
        #     for author in obj.authors.all():
        #         temp.append({"id":author.id,"name":author.name})
        #     return temp

    视图(views)

    class BookViews(APIView):
    pass
    class BookViews(其他类):
      queryset=
    Book.objects.all() #必须写queryset,不写有可能报错(源码断言处理)
    断言:
    assert self.queryset is not None, ( "'%s' should either include a `queryset` attribute, " "or override the `get_queryset()` method." % self.__class__.__name__ )

    1.继承APIView类(继承了View)

    处理Book表全部信息,查看、添加
    class BookViews(APIView):
        def get(self,request,*args,**kwargs):
            book_list=Book.objects.all()
            # querset数据转化为json数据
            bs=BookModelSerializer(book_list,many=True)  #queryset时,many=True;单个对象时,默认many=False
            # bs.data序列化后的数据[{},{}]
            return Response(bs.data)
    
        def post(self,request,*args,**kwargs):
            # 获取前端提交的数据
            obj=request.data
            #json数据转化为queryset数据
            bs=BookModelSerializer(data=obj)
            # 验证
            if bs.is_valid():
                bs.save()
                # 显示json数据
                return Response(bs.data)
            else:
                # 显示错误信息
                return Response(bs.errors)
    
    
    # 处理指定book的信息,查看、编辑、删除
    class BookDetailViews(APIView):
    
        def get(self,request,pk,*rags,**kwargs):
            book_obj=Book.objects.filter(pk=pk).first()
            if not book_obj:
                return Response("没有这条记录")
            bs=BookModelSerializer(book_obj)
            return Response(bs.data)
    
        def put(self,request,pk,*rags,**kwargs):
            # 获取编辑后的json数据
            obj=request.data
            book_obj=Book.objects.filter(pk=pk).first()
            # 将data的json数据转换为queryset(book_obj)数据
            bs=BookModelSerializer(data=obj,instance=book_obj)
            if bs.is_valid():
                bs.save()
                return Response(bs.data)
            else:
                return Response(bs.errors)
    
        def delete(self,request,pk,*args,**kwargs):
            Book.objects.filter(pk=pk).delete()
            return Response("删除成功")

    2.使用Mixin类(ListModelMixin等中实现了增删改查方法)

    from rest_framework import mixins
    from rest_framework import generics
    
    class BookViews(mixins.ListModelMixin,
                    mixins.CreateModelMixin,
                    generics.GenericAPIView):
    
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer
        # 继承mixins.ListModelMixin
        def get(self,request,*args,**kwargs):
            return self.list(request, *args, **kwargs)
    
        # 继承mixins.CreateModelMixin
        def post(self,request,*args,**kwargs):
            return self.create(request,*args,**kwargs)
    
    
    class BookDetailViews(mixins.RetrieveModelMixin,
                          mixins.UpdateModelMixin,
                          mixins.DestroyModelMixin,
                          generics.GenericAPIView):
        # lookup_field = 'pk' 找到url(r'^books/(?P<pk>d+)/$', views.BookDetailViews.as_view())generics.GenericAPIView中默认设置好了,先queryset查询再进行过滤
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer
    
        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)

    3.使用通用的基于类视图

    from rest_framework import generics
    ListCreateAPIView继承mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView
    
    class BookViews(generics.ListCreateAPIView):
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer
    
    class BookDetailViews(generics.RetrieveUpdateDestroyAPIView):
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

    4.终极版viewsets.ModelViewSet(重新定义了as_view())

    ###############终极版viewsets.ModelViewSet###########
    
    from rest_framework import viewsetsclass BookViewsSet(viewsets.ModelViewSet): 
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

    urls.py
      url(r'^books/$',views.BookViewsSet.as_view({"get":"list","post":"create"})),
      url(r'^books/(?P<pk>d+)/$',views.BookViewsSet.as_view({"get":"retrieve","put":"update","delete":"destr

    ModelViewSet类的继承关系(自己有的用自己的,自己没有的用父类的)

    解释器(parser)

    根据请求头content_type对应的的解析器类型进行请求体处理

    urlencoded 对应 格式一:name=alex&age=123&email=131232         json 对应 格式二:{name:'xx',age:'xxx'}
    1、Django中的request类:
      from django.core.handlers.wsgi import WSGIRequest
      只是对 "multipart/form-data"(上传文件)和"application/x-www-form-urlencoded"(如form表单)进行了处理,其他类型的请求头,都要进行解码和反序列化(json.loads.(request.body.decode="utf8"))
      只有在content_type="multipart/form-data"或"application/x-www-form-urlencoded"时,request.POST中才有数据request.body中有元数据
    2、rest_frmaework中的request类:
      from rest_framework.parsers import JSONParser,FileUploadParser,FormParser,MultiPartParser
      rest_frmaework:中将解析器的种类扩大有 JSONParser,FileUploadParser,FormParser,MultiPartParser所有数据都在request.data中
      个别特殊的值可以通过request._request 来进行获取 因为它对Django中的request进行了二次封装

        第一次:
            头:
              content-type: application/x-www-form-urlencoded
            体:
              k1=v1&k2=v2
            request.data 接收到的是QueryDict类型

        第二次:
            头:
              content-type: application/json
            体:
              {"k1":"v1","k2":"v2"}

            reuqest.data 接收到的是dict类型

    在rest_frmaework中:

    局部使用parser:

    views.py

    from rest_framework.parsers import JSONParser,FormParser,FileUploadParser,MultiPartParser 默认使用JSONParser,FormParser
    class BookViewsSet(viewsets.ModelViewSet): #重新定义了as_view()
    # 解析器
    parser_classes=[JSONParser,FileUploadParser,FormParser,MultiPartParser]

    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    全局使用parser:

    settings.py

    REST_FRAMEWORK={# 解析器
        "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FileUploadParser",] }

    分页(page)

    一、自定义页码分页

    1.自定义list()分页

    view.py

    from rest_framework.pagination import PageNumberPagination
    class BookViewsSet(viewsets.ModelViewSet): #重新定义了as_view()
    
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer
    
        #自定义list ,分页
        def list(self,request,*args,**kwargs):
            book_list=Book.objects.all()
            print(book_list)
            pnp=PageNumberPagination()
            pager_book=pnp.paginate_queryset(queryset=book_list,request=request,view=self)
            print("pager_book",pager_book)
            # 序列化分页后的数据
            bs=BookModelSerializer(pager_book,many=True)
            return pnp.get_paginated_response(bs.data)

    settings.py

    REST_FRAMEWORK={
    #     自定义list()分页,每页显示的个数
        "PAGE_SIZE": 2
    }

    2.自定义页码分页

    pageing.py

    from rest_framework.pagination import PageNumberPagination
    class PageBook(PageNumberPagination):
        page_size = 1
        page_query_param = 'page'
        page_size_query_param = "size"
        max_page_size =1

    views.py

    class BookViewsSet(viewsets.ModelViewSet): #重新定义了as_view()
        # 分页
        pagination_class=PageBook
    
    
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

    二、按照索引和每页显示的个数

    pageing.py

    from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
    
    #用法http://127.0.0.1:8001/books/?offset=1&limit=2   根据起始索引和每页显示的个数
    class PageBook(LimitOffsetPagination):
        # 默认每页显示的数据条数
        default_limit = 2
        # URL中传入的显示数据条数的参数
        limit_query_param = 'limit'
        # URL中传入的数据位置的参数
        offset_query_param = 'offset'
        # 最大每页显得条数
        max_limit = None

    views.py

    class BookViewsSet(viewsets.ModelViewSet): #重新定义了as_view()
        # 分页
        pagination_class=PageBook
    
    
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

    三、游标分页

    pageing.py

    # 游标分页  对cursor进行加密,只能通过指定的url进行访问(只能通过图片中的url访问)
    
    class PageBook(CursorPagination):
        # URL传入的游标参数
        cursor_query_param = 'page'
        # 默认每页显示的数据条数
        page_size = 2
        # URL传入的每页显示条数的参数
        page_size_query_param = 'page_size'
        # 每页显示数据最大条数
        max_page_size = 1000
    
        # 根据ID从大到小排列
        ordering = "id"

    views.py

    class BookViewsSet(viewsets.ModelViewSet): #重新定义了as_view()
        # 分页
        pagination_class=PageBook
    
    
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

     路由系统

    1.自定义路由

      http://127.0.0.1:8001/books/?format=json   浏览器中可以直接访问json数据
      url(r'^books/$',views.BookViewsSet.as_view({"get":"list","post":"create"})),

      #http://127.0.0.1:8001/books.json 或 http://127.0.0.1:8001/books/?format=json 浏览器中可以直接访问json数据
    url(r'^books.(?P<format>[a-z0-9]+)$',views.BookViewsSet.as_view({"get":"list","post":"create"})),

    2.自动生成url

    # 自动生成url
    from django.conf.urls import url,include
    from api import views
    from rest_framework import routers
    
    router = routers.DefaultRouter()
    router.register(r'books', views.BookViewsSet)
    
    urlpatterns = [
    
        # 自动生成url
        url(r'^',include(router.urls)),
    ]

    响应器

    根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
    用户请求URL:

      http://127.0.0.1:8000/books/?format=json

      http://127.0.0.1:8000/books.json

      http://127.0.0.1:8000/books

    用户请求头:

      Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

    from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer,AdminRenderer,HTMLFormRenderer,TemplateHTMLRenderer

    以下访问urls.py都一样

    urlpatterns = [
        url(
        # http://127.0.0.1:8001/books/?format=json或http://127.0.0.1:8001/books.json #浏览器中可以直接访问json数据
        url(r'^books.(?P<format>[a-z0-9]+)$',views.BookViewsSet.as_view({"get":"list","post":"create"})),  
    ]

    1. 访问json

    urls.py:

      http://127.0.0.1:8000/books/?format=json
    
      http://127.0.0.1:8000/books.json
    
      http://127.0.0.1:8000/books

    views.py

    class BookViewsSet(viewsets.ModelViewSet): 
    # 响应器
    renderer_classes=[JSONRenderer]
        queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    2.表格

    urls.py:

      http://127.0.0.1:8000/books/?format=admin
    
      http://127.0.0.1:8000/books.admin
    
      http://127.0.0.1:8000/books

    views.py

    class BookViewsSet(viewsets.ModelViewSet): 
    # 响应器
    renderer_classes=[AdminRenderer]
        queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    3.form表单

    urls.py:

      http://127.0.0.1:8000/books/?format=form
    
      http://127.0.0.1:8000/books.form
    
      http://127.0.0.1:8000/books

    views.py

    class BookViewsSet(viewsets.ModelViewSet): 
    # 响应器
    renderer_classes=[HTMLFormRenderer]
        queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    4.自定义显示模板

    urls.py:

      http://127.0.0.1:8000/books/?format=html
    
      http://127.0.0.1:8000/books.html
    
      http://127.0.0.1:8000/books

    views.py

    class BookViewsSet(viewsets.ModelViewSet): 
    # 响应器
    renderer_classes=[TemplateHTMLRenderer,]
      def get(self, request, *args, **kwargs):
             book_list = Books.objects.all()
             bs = BookSerializer(instance=book_list, many=True)
             return Response(bs.data, template_name='books.html')

     books.html

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     {{ title }}
     9     {{ price }}11 </body>
    12 </html>

    3.form表单

    urls.py:

      http://127.0.0.1:8000/books/?format=api
    
      http://127.0.0.1:8000/books.api
    
      http://127.0.0.1:8000/books

    views.py

    class BookViewsSet(viewsets.ModelViewSet): 
    # 响应器
    renderer_classes=[renderer_classes=[HTMLFormRenderer]]
        queryset = Book.objects.all()
    serializer_class = BookModelSerializer

    待续

  • 相关阅读:
    Flask-SQLAlchemy 学习总结
    ubuntu安装redis
    PostgreSQL在Ubuntu上安装指南
    Linux(Ubuntu)下MySQL的安装与配置
    python wechat_sdk间接性的出现错误OfficialAPIError: 40001,说access_token已过期或者不是最新的。
    django不要设置datetime字段auto_now=True
    python 装饰器和 functools 模块
    关于 Python Iterator 协议的一点思考
    python中的enumerate函数
    8 种常被忽视的 SQL 错误用法
  • 原文地址:https://www.cnblogs.com/caochao-/p/8747715.html
Copyright © 2011-2022 走看看