两个基类,五大扩展类,还有九个视图子类

两个基类,五大扩展类,还有九个视图子类

谈论这几个之前我们应该也要首先去了解一下rest_framework.

一、什么是rest_framework
它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架。
安装方式有很多种,可以通过pip,或者在pycharm中安装也可以
至于什么是restful规范可以自行百度一下·····
一直在说 Django REST framework,那它到底是什么,你是怎么理解的呢?我查了一些资料,对Django REST framework有了一些粗浅的理解,记录下来。(通常简称Django REST framework为DRF框架)。

github链接。

从字面理解开始
仅从字面意思理解的话,Django和framework指的是Django,框架。那REST呢?

REST是Representational State Transfer的简称,中文翻译为“表现层状态转化”,REST与技术无关,代表的是一种软件架构风格,遵循REST的架构风格,称为RESTful。
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。
他在介绍他的论文时说到:
“网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。”

Fielding将他对互联网软件的架构原则,定名为REST,即Representational State Transfer的缩写。
如果我把rest译为:使人轻松的,让人得到休息的,不知道他会怎么想,哈哈,但是为了便于理解,我们不妨再暂且这么认为。
RESTful架构风格,因其可扩展性和简单性受到越来越多的架构师和开发者们的青睐,时至今日,RESTful架构风格已成为企业级服务的标配。

RESTful
现在我们来到了RESTful,RESTful是什么呢?RESTful有三个基本概念和一些显著特点。

资源
首先需要注意的是,REST的名称"表现层状态转化"中,省略了主语,主语就是资源(Resources),资源是网络上的一个实体,或者说是网络上的一个具体信息,可以是文本、图片、音视频等。RESTful 架构风格的服务是围绕资源展开的,是典型的ROA(面向资源架构)。
表现层
“资源"可以有多种外在表现形式,我们把"资源"具体呈现出来的形式,叫做它的"表现层”(Representation)。如:文本可以是txt格式,图片可以是jpg、png格式等,JSON是现在最常用的资源表示格式。
状态转化
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。
  互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer),而这种转化是建立在表现层之上的。
特点:统一接口
RESTful架构风格规定,数据的元操作,即CRUD(create, read, update和delete)操作,分别对应于HTTP方法:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,这样就统一了数据操作的接口,仅通过HTTP方法,就可以完成对数据的所有增删查改工作。
HTTP动词 SQL命令 含义
GET SELECT 从服务器取出资源(一项或多项)
POST CREATE 在服务器新建一个资源
PUT UPDATE 在服务器更新资源
DELETE DELETE 从服务器删除资源
PATCH UPDATE 在服务器更新资源
HEAD ----- 获取资源的元数据
OPTIONS ----- 获取信息,关于资源的哪些属性是客户端可以改变的
特点:URI(统一资源定位符)
可以用一个URI(统一资源定位符)指向资源,即每个URI都对应一个特定的资源。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或识别符。
一般的,每个资源至少有一个URI与之对应,最典型的URI即URL。
特点:路径(Endpoint)
资源作为网址,只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应。
以下是不好的例子:
/getProducts # 获取所有商品
/listOrders # 查询列举所有订单

对于一个简洁结构,你应该始终用名词, 如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。
API中的名词应该使用复数。无论子资源或者所有资源。

举例来说,获取产品的API可以这样定义
获取单个产品:http://127.0.0.1:8080/products/1
获取所有产品: http://127.0.0.1:8080/products
特点:无状态
所谓无状态的,即所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。
有状态和无状态的区别,举个简单的例子说明一下。如查询员工的工资,如果查询工资是需要登录系统,进入查询工资的页面,执行相关操作后,获取工资的多少,则这种情况是有状态的,因为查询工资的每一步操作都依赖于前一步操作,只要前置操作不成功,后续操作就无法执行;如果输入一个url即可得到指定员工的工资,则这种情况是无状态的,因为获取工资不依赖于其他资源或状态,且这种情况下,员工工资是一个资源,由一个url与之对应,可以通过HTTP中的GET方法得到资源,这是典型的RESTful风格。
Django REST framework
Tom Christie 在Django框架的基础之上,进行二次开发,便有了Django REST framework,DRF是一个用于构建Web API 的强大而又灵活的工具。
github链接
官方文档

主要特点
提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 - API,满足各种需要;
多种身份认证和权限认证方式的支持;
内置了限流系统;
直观的 API web 界面;
可扩展性,插件丰富
所以,Django REST framework 是:基于Django,遵循RESTful风格的框架。

APIview

首先是导入

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

APIView与View的不同之处在于:

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

支持定义的列属性

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

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

导入APIView
from rest_framework.views import APIView
导入Response
from rest_framework.response import Response
路由:   path('books/',views.BooksViews.as_view(),name='books'),
views.py:
class BooksView(APIView):
   def get (self,request):
       books_list=Books.objects.all()
       serializer=BooksSerializer(instance=books_list, many=True)
       return Response(serializer.data)
  """model 和serializer根据自己实际业务需求来写"""

GenericAPIView

首先还是导入:from rest_framework.generics import GenericAPIView

继承自APIVIew主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。

提供的关于序列化器使用的属性与方法

  • 属性:

    • serializer_class 指明视图使用的序列化器

  • 方法:

    • get_serializer_class(self)

      当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。

get_serializer(self, args, *kwargs)
返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。

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

request 当前视图的请求对象
view 当前请求的类视图对象
format 当前请求期望返回的数据格式
提供的关于数据库查询的属性与方法

属性:

queryset 指明使用的数据查询集
方法:

get_queryset(self)

返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:
def get_queryset(self):
   user = self.request.user
   return user.accounts.all()
get_object(self)

返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。

在试图中可以调用该方法获取详情信息的模型类对象。

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

该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
class BookDetailView(GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer

def get(self, request, pk):
book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象
serializer = self.get_serializer(book)
return Response(serializer.data)
queryset = None
serializer_class = None

def get_queryset(self): # 查表的所有
def get_object(self): # 查单个
def get_serializer(self, *args, **kwargs): # 得到序列化类的对象,传instance,data,many.


filter_backends = 过滤类
pagination_class = 分页类

2、django本地化(国际化)配置

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai' # 时区必须大写
USE_I18N = True
USE_L10N = True
USE_TZ = False

 

from rest_framework.generics import GenericAPIView

from students.models import Student
from .serializers import StudentModelSerializer, StudentModel2Serializer
from rest_framework.response import Response

class StudentsGenericAPIView(GenericAPIView):
# 本次视图类中要操作的数据[必填]
queryset = Student.objects.all()
# 本次视图类中要调用的默认序列化器[选填]
serializer_class = StudentModelSerializer

def get(self, request):
"""获取所有学生信息"""
serializer = self.get_serializer(instance=self.get_queryset(), many=True)

return Response(serializer.data)

def post(self,request):

data = request.data

serializer = self.get_serializer(data=data)

serializer.is_valid(raise_exception=True)

instance = serializer.save()

serializer = self.get_serializer(instance=instance)

return Response(serializer.data)


class StudentGenericAPIView(GenericAPIView):
queryset = Student.objects.all()

serializer_class = StudentModelSerializer

def get_serializer_class(self):
"""重写获取序列化器类的方法"""
if self.request.method == "GET":
return StudentModel2Serializer
else:
return StudentModelSerializer

# 在使用GenericAPIView视图获取或操作单个数据时,视图方法中的代表主键的参数最好是pk
def get(self,request,pk):
"""获取一条数据"""
serializer = self.get_serializer(instance=self.get_object())

return Response(serializer.data)

def put(self,request,pk):

data = request.data

serializer = self.get_serializer(instance=self.get_object(),data=data)

serializer.is_valid(raise_exception=True)

serializer.save()

serializer = self.get_serializer(instance=self.get_object())

return Response(serializer.data)

序列化类

from rest_framework import serializers

from students.models import Student

class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model= Student
fields = "__all__"


class StudentModel2Serializer(serializers.ModelSerializer):
class Meta:
model= Student
fields = ("name","class_null")

5个视图扩展类

首先列举一下那五个

RetrieveModelMixin     # 查询单条,类里有retrieve方法
ListModelMixin, # 查询所有,类里有list方法
CreateModelMixin, # 增加, 类里有create方法
DestroyModelMixin, # 删除, 类里有destroy方法
UpdateModelMixin, # 更新, 类里有update方法

都是以modelmixin结尾,每个类里只写了一个自己的功能。 视图类需要继承view/APIView,这五个没继承,所以是视图扩展类。

提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

ListModelMixin

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

源代码

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)

代码举例

from rest_framework.mixins import ListModelMixin
刚才我们也说到GenericAPIView是这五个扩展类的父类,所以这五个方法继承搭配要配合GenericAPIView
class BookListView(ListModelMixin, GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer

def get(self, request):
return self.list(request)

CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图

源代码

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 {}

RetrieveModelMixin

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

源代码:

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)
代码举例
class BookDetailView(RetrieveModelMixin, GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer

def get(self, request, pk):
return self.retrieve(request)

UpdateModelMixin

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

同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
源代码:
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)

estroyModelMixin

删除视图扩展类,提供`destroy(request, *args, **kwargs)`方法,可以快速实现删除一个存在的数据对象。
源代码:
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()

 

继承GenericAPIView+5个视图扩展类实现5个接口

继承GenericAPIView+5个视图扩展类实现5个接口


class ListModeMixin():
def list(self, request):
print('dsafdasdfasd')
book_list = self.get_queryset() # 获取要序列化的数据,不要直接使用self.queryset,而要用self.get_queryset()

# 获取序列化类,要使用self.get_serializer
ser = self.get_serializer(instance=book_list, many=True)
print(type(ser)) # ListSerializer的对象---》[BookSerializer,BookSerializer,BookSerializer]
return Response(ser.data)

from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = Book.objects.all() # 要序列化的数据
serializer_class = BookSerializer # 序列化类

def get(self,request):
print('获取所有')
return super().list(request)



def post(self, request):
return super().create(request)


class BookDetailView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = Book.objects.all() # 要序列化的数据
serializer_class = BookSerializer # 序列化类
#传入的必须叫pk,否则,get_object就拿不到对象
def get(self, request, *args, **kwargs):
print('获取一')
return super().retrieve(request, *args, **kwargs)

# put:全局修改 patch:局部修改
def put(self, request, *args, **kwargs): # pk 从kwargs中去
return super().update(request, *args, **kwargs)

def delete(self,request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)

九个视图子类

 GenericAPIView的视图子类
1)CreateAPIView
提供 post 方法

继承自: GenericAPIView、CreateModelMixin

2)ListAPIView
提供 get 方法

继承自:GenericAPIView、ListModelMixin

3)RetrieveAPIView
提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

4)DestoryAPIView
提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

5)UpdateAPIView
提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

6)RetrieveUpdateAPIView
提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法

继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
 

from rest_framework.generics import
ListAPIView, # 查询所有
CreateAPIView, # 增加
RetrieveAPIView, # 查询单条
UpdateAPIView, # 更新
DestroyAPIView, # 删除
# 下面这4个是组合
ListCreateAPIView, # 查询所有、增加
RetrieveUpdateDestroyAPIView, # 查询单条、更新、删除
RetrieveDestroyAPIView, # 查询单条、删除
RetrieveUpdateAPIView # 查询单条、更新

序列化组件

序列化器

首先我们来了解序列化器他的一个作用
1.序列化:序列化器会把模型对象转换成字典经过response以后转成我们熟知的Jason字符串
2.反序列化:他会把客户端发送过来的数据,经过request以后传过来以后变成字典,序列化器可以把字典转换成一个模型,并且反序列化具有数据校验功能

定义序列化器

首先我们有一个数据库的模型类(students)

from django.db import models

class Student(models.Model):
# 模型字段
name = models.CharField(max_length=100,verbose_name="姓名",help_text="提示文本:账号不能为空!")
sex = models.BooleanField(default=True,verbose_name="性别")
age = models.IntegerField(verbose_name="年龄")
class_null = models.CharField(max_length=5,verbose_name="班级编号")
description = models.TextField(verbose_name="个性签名")

class Meta:
db_table="tb_student"
verbose_name = "学生"
verbose_name_plural = verbose_name

然后我们来进行序列化器的定义

导入:
from rest_framework import serializers

# 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
# 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化
class StudentSerializer(serializers.Serializer):
"""学生信息序列化器"""
# 1. 需要进行数据转换的字段
id = serializers.IntegerField()
name = serializers.CharField()
age = serializers.IntegerField()
sex = serializers.BooleanField()
description = serializers.CharField()
(继承Serializer之后定义的序列化组件中的字段要跟models模型层中表的字段一一对应)
注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。
 
posted @   文质彬彬赵其辉  阅读(315)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示