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

待续

原文地址:https://www.cnblogs.com/caochao-/p/8747715.html