视图

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

视图的继承关系:

视图的方法与属性:

Request 与 Response

Request

文档

1
from rest_framework.request import Request

REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

常用属性

1)data

request.data返回解析之后的请求体数据。类似于Django中标准的request.POST属性,但提供如下特性:

  • 包含了对POST、PUT、PATCH请求方式解析后的数据

  • 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    from rest_framework.request import Request
    class Request:

    @property
    def data(self):
    if not _hasattr(self, '_full_data'):
    self._load_data_and_files()
    return self._full_data

    def _load_data_and_files(self):
    """
    Parses the request content into `self.data`.
    """
    if not _hasattr(self, '_data'):
    self._data, self._files = self._parse()
    if self._files:
    self._full_data = self._data.copy()
    self._full_data.update(self._files)
    else:
    self._full_data = self._data

    # if a form media type, copy data & files refs to the underlying
    # http request so that closable objects are handled appropriately.
    if is_form_media_type(self.content_type):
    self._request._post = self.POST
    self._request._files = self.FILES
2)query_params

request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。

1
2
3
4
5
6
7
8
9
from rest_framework.request import Request

class Request:
@property
def query_params(self):
"""
More semantically correct name for request.GET.
"""
return self._request.GET

Response

文档

1
rest_framework.response.Response

REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

REST framework提供了Renderer渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。

1
2
3
4
5
6
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}

默认返回json数据

设置Accept为text/html就可以返回html数据

1.构造方式

1
Response(data, status=None, template_name=None, headers=None, content_type=None)

data只需传递python的内建类型数据即可。

data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。

参数说明:

  • data: 为响应准备的序列化处理后的数据;
  • status: 状态码,默认200;
  • template_name: 模板名称,如果使用HTMLRenderer时需指明;
  • headers: 用于存放响应头信息的字典;
  • content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

2.常用属性:

1)data

传给response对象的序列化后,但尚未render处理的数据

2)status_code

状态码的数字

3. status_code状态码

文档

为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。

1)信息告知 - 1xx
1
2
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2)成功 - 2xx
1
2
3
4
5
6
7
8
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3)重定向 - 3xx
1
2
3
4
5
6
7
8
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4)客户端错误 - 4xx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5)服务器错误 - 5xx
1
2
3
4
5
6
7
8
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

视图

文档

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

视图的继承关系:

视图的方法与属性:

APIView(一级)

1
rest_framework.views.APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIViewView的不同之处在于:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。

支持定义的属性:

  • authentication_classes列表或元祖,身份认证类
  • permissoin_classes列表或元祖,权限检查类
  • throttle_classes列表或元祖,流量控制类

APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class BookListAPIView(APIView):

def get(self,request):

# request.GET
# request.query_params
#params = request.query_params
# 1.查询数据
books = BookInfo.objects.all()
# 2.创建序列化器,并传递查询结果集(设置many=True)
serializer = BookInfoModelSerializer(books, many=True)
# 3.返回响应 serializer.data 就是字典列表
return Response(serializer.data)

def post(self,request):

# request.POST, request.body
#data = request.data

# 1.接收参数
book_dict = request.data
# 2.创建序列化器,并传递参数
serializer = BookInfoModelSerializer(data=book_dict)
# 3.验证数据,并根据验证结果进行判断
if serializer.is_valid():
# 4.数据验证没有问题,调用序列化器的save方法。来触发序列化器的create方法
# create方法会调用模型来保存到数据库中
serializer.save()
# 5. 返回响应 serializer.data 就是字典数据
return Response(serializer.data)
else:
# 返回错误信息
return Response({'msg':'保存失败'})

GenericAPIView(二级)

文档

1
rest_framework.generics.GenericAPIView

继承自APIVIew,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

使用GenericAPIView类一般需要实现queryset属性或者重写get_queryset方法

支持定义的属性:

  • 列表视图与详情视图通用:
    • queryset列表视图的查询集
    • serializer_class视图使用的序列化器
  • 详情页视图使用:
    • lookup_field查询单一数据库对象时使用的条件字段,默认为’pk
    • lookup_url_kwarg查询单一数据时URL中的参数关键字名称,默认与look_field相同

提供的方法:

  • 列表视图与详情视图通用:
    • get_queryset(self)

      返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:

      1
      2
      def get_queryset(self):
      return BookInfo.objects.all()
    • get_serializer_class(self)

      返回序列化器类,默认返回serializer_class,可以重写,例如:

      1
      2
      def get_serializer_class(self):
      return BookInfoModelSerializer
    • get_serializer(self,_args, *_kwargs)

      返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。

      注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

  • 详情视图使用:
    • get_object(self)返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。

      若详情访问的模型类对象不存在,会返回404。

列表视图方法和属性举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from rest_framework.generics import GenericAPIView
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer

class BookListGenericView(GenericAPIView):

# 设置查询结果集属性
queryset = BookInfo.objects.all()

# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def get(self,request):
# 1.查询数据
books = self.get_queryset()
# 2.创建序列化器,并传递查询结果集(设置many=True)
serializer = self.get_serializer(books, many=True)
# 3.返回响应 serializer.data 就是字典列表
return Response(serializer.data)

def post(self,request):
# 1.接收参数
book_dict = request.data
# 2.创建序列化器,并传递参数
serializer = self.get_serializer(data=book_dict)
# 3.验证数据,并根据验证结果进行判断
if serializer.is_valid():
# 4.数据验证没有问题,调用序列化器的save方法。来触发序列化器的create方法
# create方法会调用模型来保存到数据库中
serializer.save()
# 5. 返回响应 serializer.data 就是字典数据
return Response(serializer.data)
else:
# 返回错误信息
return Response({'msg': '保存失败'})

我们还可以通过以下方法来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
class BookListGenericView(GenericAPIView):

# 设置查询结果集属性
# queryset = BookInfo.objects.all()
#重写查询结果集方法
def get_queryset(self):
return BookInfo.objects.all()

# 设置序列化器属性
# serializer_class = BookInfoModelSerializer
# 重写返回序列化器方法
def get_serializer_class(self):
return BookInfoModelSerializer

详情视图方法和属性举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from rest_framework.generics import GenericAPIView
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer

class BookDetailGenericView(GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 重写查询结果集方法
# def get_queryset(self):
# return BookInfo.objects.all()

# 设置序列化器属性
serializer_class = BookInfoModelSerializer
# 重写返回序列化器方法
# def get_serializer_class(self):
# return BookInfoModelSerializer

# 默认是pk
# 可以修改为 id, 如果修改,
# 则 get,put,delete 方法中的关键字参数都要改变
lookup_field = 'pk'

def get(self,request,pk):
#1.查询指定书籍
book = self.get_object()
#2.创建序列化器,传递模型对象
serializer = self.get_serializer(book)
#3.获取字典数据,并返回响应
return Response(serializer.data)

def put(self,request,pk):
#1.查询指定书籍
book = self.get_object()
#2.创建序列化器,传递模型对象和接收的参数
serializer = self.get_serializer(instance=book,data=request.data)
# 3.验证数据,并根据验证结果进行判断
if serializer.is_valid():
# 4.数据验证没有问题,调用序列化器的save方法。来触发序列化器的update方法
# update方法会调用模型来更新到数据库中
serializer.save()
# 5. 返回响应 serializer.data 就是字典数据
return Response(serializer.data)
else:
# 返回错误信息
return Response({'msg': '保存失败'})

def delete(self,request,pk):
#1.查询指定书籍
book = self.get_object()
#2.删除
book.delete()
#3.返回响应
from rest_framework import status
return Response(status=status.HTTP_204_NO_CONTENT)

Mixin

文档

1)ListModelMixin

列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

该Mixin的list方法会对数据进行过滤和分页。

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())

page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)

serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer


class BookListGenericMixinView(ListModelMixin,GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def get(self,request):
#调用Mixin抽取好的list方法
return self.list(request)

2)CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

def perform_create(self, serializer):
serializer.save()

def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer


class BookListGenericMixinView(CreateModelMixin,GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def post(self,request):
# 调用Mixin抽取好create的方法
return self.create(request)

3)RetrieveModelMixin

详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。

如果存在,返回200, 否则返回404。

源代码:

1
2
3
4
5
6
7
8
class RetrieveModelMixin(object):
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer


class BookDetailGenericMixinView(RetrieveModelMixin, GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def get(self, request,pk):
# 调用Mixin抽取好的retrieve方法
return self.retrieve(request)

4)UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class UpdateModelMixin(object):
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)

if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}

return Response(serializer.data)

def perform_update(self, serializer):
serializer.save()

def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import UpdateModelMixin
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer


class BookDetailGenericMixinView(UpdateModelMixin, GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def put(self, request,pk):
# 调用Mixin抽取好update的方法
return self.update(request)

5)DestroyModelMixin

删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。

成功返回204,不存在返回404。

源代码:

1
2
3
4
5
6
7
8
9
10
11
class DestroyModelMixin(object):
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)

def perform_destroy(self, instance):
instance.delete()

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import DestroyModelMixin
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer


class BookDetailGenericMixinView(DestroyModelMixin, GenericAPIView):
# 设置查询结果集属性
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer

def delete(self,request,pk):
调用Mixin抽取好destory的方法
return self.destroy(request)

子类视图(三级)

1)CreateAPIView

1
from rest_framework.generics import CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

1
2
3
4
5
6
7
class CreateAPIView(mixins.CreateModelMixin,
GenericAPIView):
"""
Concrete view for creating a model instance.
"""
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

2)ListAPIView

1
from rest_framework.generics import ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

1
2
3
4
5
6
7
class ListAPIView(mixins.ListModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)

3)RetireveAPIView

1
from rest_framework.generics import RetrieveAPIView

提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

4)DestoryAPIView

1
from rest_framework.generics import DestroyAPIView

提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

5)UpdateAPIView

1
from rest_framework.generics import UpdateAPIView

提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

6)RetrieveUpdateAPIView

1
from rest_framework.generics import RetrieveUpdateAPIView

提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

7)RetrieveUpdateDestoryAPIView

1
from rest_framework.generics import RetrieveUpdateDestroyAPIView

提供 get、put、patch、delete方法

继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

视图集ViewSet

文档

Django REST框架允许将一组相关视图的逻辑组合到一个类中,称为ViewSet

一个ViewSet类只是一种基于类的View,它不提供任何方法处理程序(如get()orpost()),而是提供诸如list()create()之类的操作。

使用ViewSet类比使用View类有两个主要优点。

  • 重复的逻辑可以合并成一个类。例如我们只需要指定queryset一次,它将用于多个视图。
  • 通过使用路由器,我们不再需要处理自己的URL配置

ViewSet

一个ViewSet类只是一种基于类的View,继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

在ViewSet中,它不提供任何方法处理程序,需要我们自己重写该类并明确实现action方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class BookViewSet(viewsets.ViewSet):

def list(self, request):
pass

def create(self, request):
pass

def retrieve(self, request, pk=None):
pass

def update(self, request, pk=None):
pass

def partial_update(self, request, pk=None):
pass

def destroy(self, request, pk=None):
pass

一个ViewSet类同时提供以下可用属性

  • basename- 用于创建的URL名称的基础。
  • action- 当前动作的名称(例如listcreate)。
  • detail- 布尔值,指示当前操作是否为列表或详细视图配置。
  • suffix- 视图类型的显示后缀 - 镜像detail属性。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from rest_framework.viewsets import ViewSet
from django.shortcuts import get_object_or_404
from rest_framework.response import Response
from book.serializers import BookInfoModelSerializer

class BookViewSet(ViewSet):

def list(self,request):
queryset = BookInfo.objects.all()
serializer = BookInfoModelSerializer(queryset,many=True)
return Response(serializer.data)

def retrieve(self,request,pk=None):
queryset = BookInfo.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = BookInfoModelSerializer(user)
return Response(serializer.data)

在设置路由时,我们可以如下操作

1
2
3
4
5
6
from django.urls import re_path
from book import views
urlpatterns = [
re_path(r'^books/$',views.BookViewSet.as_view({'get':'list'})),
re_path(r'^books/(?P<pk>\d+)/$',views.BookViewSet.as_view({'get':'retrieve'})),
]

替代方案为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.urls import re_path
from book import views

urlpatterns = [
#re_path(r'^books/$',views.BookViewSet({'get':'list'})),
#re_path(r'^books/(?P<pk>\d+)/$',views.BookViewSet({'get':'retrieve'})),
]

from rest_framework.routers import DefaultRouter
# 1. 创建router实例
rounter = DefaultRouter()
# 2. 设置列表视图和详情视图的公共部分(不包括/部分)
# prefix, 路由. 列表视图和详情视图的公共部分(不包括最后的/部分)
# router会生成2个路由,一个是列表视图的路由 prefix.另外一个是详情视图的路由 prefix/pk/
# viewset, 视图集
# basename=None 给列表视图和详情视图的路由设置别名.
# 别名的规范是 列表视图是: basename-list 详情视图是: basename-detail
# 因为 别名的原因.所以 basename 不要重复.一般我们都是以 prefix 作为basename.因为prefix不会重复
rounter.register('books',views.BookViewSet,basename='')

# 3.将router生成的路由,追加到 urlpatterns
urlpatterns += rounter.urls

注意: 通常情况下,我们经常使用提供默认行为集的现有基类,例如ModelViewSet

GenericViewSet

文档

继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。在GenericAPIView中,没有提供任何动作action方法,需要我们自己覆盖该类并混合所需的混合类,或者明确定义操作实现action方法

ModelViewSet

文档

继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

ModelViewSet类所继承GenericAPIView,包括用于各种动作实现方式中,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

由提供的动作ModelViewSet类是.list().retrieve().create().update().partial_update(),和.destroy()

使用:

因为ModelViewSet扩展GenericAPIView,我们通常需要提供至少querysetserializer_class属性

1
2
3
4
5
6
7
8
from rest_framework.viewsets import ModelViewSet
from book.serializers import BookInfoModelSerializer
from book.models import BookInfo

class BookModelViewSet(ModelViewSet):

queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer

在设置路由时,我们可以如下操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from book import views
urlpatterns = [
]

from rest_framework.routers import DefaultRouter
# 可以处理视图的路由器
router = DefaultRouter()
# 1. 创建router实例
router=SimpleRouter()
# 2. 设置列表视图和详情视图的公共部分(不包括/部分)
# prefix, 路由. 列表视图和详情视图的公共部分(不包括最后的/部分),比如访问127.0.0.1:8000/books
# router会生成2个路由,一个是列表视图的路由 prefix.另外一个是详情视图的路由 prefix/pk/
# viewset, 视图集
# basename=None 给列表视图和详情视图的路由设置别名.
# 别名的规范是 列表视图是: basename-list 详情视图是: basename-detail
# 因为 别名的原因.所以 basename 不要重复.一般我们都是以 prefix 作为basename.因为prefix不会重复
router.register('books', views.BookModelViewSet,basename='')
# 3.将router生成的路由,追加到 urlpatterns
urlpatterns += router.urls

ReadOnlyModelViewSet

文档

继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。

ModelViewSet它一样,它还包括各种操作的实现,但不同于ModelViewSet只提供“只读”操作,list()而且retrieve()

路由Router

文档

对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由列表信息。

REST framework提供了两个router

  • SimpleRouter
  • DefaultRouter

1. 使用方法

1) 创建router对象,并注册视图集,注册语法为

1
register(prefix, viewset,basename)
  • prefix 该视图集的路由前缀
  • viewset 视图集
  • basename路由名称的前缀

例如

1
2
3
4
5
from rest_framework import routers

router = routers.DefaultRouter()

router.register(r'books', BookViewSet, basename='book')

如上述代码会形成的路由如下:

1
2
^books/$    name: book-list
^books/{pk}/$ name: book-detail

2)添加路由数据

可以有两种方式:

1
2
3
4
urlpatterns = [
...
]
urlpatterns += router.urls

1
2
3
4
urlpatterns = [
...
path('', include(router.urls))
]

2. 路由router形成URL的方式

1) SimpleRouter

2)DefaultRouter

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。