rest framework介绍 (CBV(class base views))

在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增、删、改、查的实现流程基本套路化,所以这部分代码也是可以复用简化编写的:

增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
删:判断要删除的数据是否存在 -> 执行数据库删除
改:判断要修改的数据是否存在 -> 校验请求的数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
查:查询数据库 -> 将数据序列化并返回

解析url中的 as_view()

url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),  

继承

APIView继承自View,APIView中有as_view方法,方法中会执行下面这段代码

执行了父类的as_view方法,得到view函数,执行dispatch方法(一切的开始)

序列化

序列化用于对用户请求数据进行验证和数据进行序列化

第一种表示方法——Serializers

from rest_framework import serializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.response import Response class BookSerializer(serializers.Serializer):
title = serializers.CharField(max_length=32)
price = serializers.IntegerField()
pub_date = serializers.DateField() class TestView(APIView):
def get(self, request, *args, **kwargs):
# 序列化,将数据库查询字段序列化为字典
obj = models.Book.objects.all()
ser = BookSerializer(obj, many=True)
# 如果不是queryset,就不用加many=True
# obj = models.Book.objects.all().first()
# ser = BookSerializer(obj, many=False)
return Response(ser.data) def post(self, request, *args, **kwargs):
# 验证,对请求发来的数据进行验证
ser = BookSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('Post请求')

第二种表示方法——ModelSerializers:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from app01 import models class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__" # 全部
# fields = ['title', 'price'] 只查两项
# depth = 2 # 查询深度
# exclude = ('price',) 除了price不查询 class TestView(APIView):
def get(self, request, *args, **kwargs):
# 序列化,将数据库查询字段序列化为字典
obj = models.Book.objects.all()
ser = BookSerializer(obj, many=True)
# 如果不是queryset,就不用加many=True
# obj = models.Book.objects.all().first()
# ser = BookSerializer(obj, many=False)
return Response(ser.data) def post(self, request, *args, **kwargs):
# 验证,对请求发来的数据进行验证
ser = BookSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
ser.save() # create 方法
return Response(ser.data)
else:
print(ser.errors)
return Response('Post请求')

特殊取值(取user_type对应的中文)

class UserInfo(models.Model):
user_type_choices = (
(1,'普通用户'),
(2,'VIP'),
(3,'SVIP'),
)
user_type = models.IntegerField(choices=user_type_choices)
class UserInfoSerializer(serializers.Serializer):
xxxxx = serializers.CharField(source="user_type") # row.user_type source将xxxx对应为user_type
oooo = serializers.CharField(source="get_user_type_display") # row.get_user_type_display() 数据:[{"xxxx":1,"oooo":"普通用户"}]

多表查询

一对多查询通过source实现

from django.db import models

class UserGroup(models.Model):
title = models.CharField(max_length=32) class UserInfo(models.Model):
user_type_choices = (
(1,'普通用户'),
(2,'VIP'),
(3,'SVIP'),
)
user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True)
password = models.CharField(max_length=64) group = models.ForeignKey("UserGroup")
roles = models.ManyToManyField("Role") class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo')
token = models.CharField(max_length=64) class Role(models.Model):
title = models.CharField(max_length=32)

models

from rest_framework.views import APIView
from rest_framework import serializers
from . import models
from rest_framework.response import Response class UserInfoSerializers(serializers.Serializer):
user_type = serializers.IntegerField()
user_type_choices = serializers.CharField(source="get_user_type_display")
group = serializers.CharField(source="group.title")   

 多对多通过自定义实现

class UserInfoSerializers(serializers.Serializer):
user_type = serializers.IntegerField()
user_type_choices = serializers.CharField(source="get_user_type_display")
group = serializers.CharField(source="group.title")
rls = serializers.SerializerMethodField() def get_rls(self, obj): # get_rls和上边rls要对应
ret = []
for item in obj.roles.all():
print(item)
ret.append({"id": item.id, "title": item.title})
return ret

View

 在视图中生成url

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^userinfo/$', views.UserInfoView.as_view(), ),
url(r'^group/(?P<pk>\d+)$', views.GroupView.as_view(), name='gp'),

urls

from rest_framework.views import APIView
from rest_framework import serializers
from . import models
from rest_framework.response import Response
from django.http import HttpResponse
import json class RoleSerializers(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = "__all__" class UserInfoSerializers(serializers.Serializer):
group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_field='group_id', lookup_url_kwarg='pk')
user_type = serializers.IntegerField()
user_type_choices = serializers.CharField(source="get_user_type_display")
# group = serializers.CharField(source="group.id")
rls = serializers.SerializerMethodField() def get_rls(self, obj):
ret = []
for item in obj.roles.all():
print(item)
ret.append({"id": item.id, "title": item.title})
return ret class UserInfoView(APIView):
def get(self, request):
obj = models.UserInfo.objects.all()
ser = UserInfoSerializers(obj, many=True, context={'request': request})
return Response(ser.data) class GroupSerializers(serializers.Serializer):
class Meta:
model = models.UserGroup
fields = '__all__' class GroupView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
obj = models.UserGroup.objects.filter(pk=pk).first()
ser = GroupSerializers(obj, many=False)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)

View

group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_field='group_id', lookup_url_kwarg='pk')
lookup_url_kwarg='pk'是和url中的(?P<pk>\d+)$'的pk对应,lookup_field='group_id'是取group的id值
ser = UserInfoSerializers(obj, many=True, context={'request': request}) context是必须添加的

序列化验证钩子(validate+校验字段名)

class RoleSerializers(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = "__all__" # 局部钩子
def validate_title(self, attrs):
if attrs.startswith(""):
raise ValidationError("不能以666开头")
return attrs # 全局钩子
def validate(self, attrs): return attrs

View

视图

a. GenericAPIView(没什么用)

from rest_framework import serializers
from . import models
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response class RoleSerializers(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__' class RoleView(GenericAPIView):
queryset = models.Role.objects.all()
serializer_class = RoleSerializers def get(self, request, *args, **kwargs):
# 获取数据
obj = self.get_queryset()
# 序列化
ser = self.get_serializer(obj, many=True)
return Response(ser.data)

View

b. GenericViewSet

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^role/$', views.RoleView.as_view({'get': 'list'}), ), # 和view里边的list方法做对应关系

urls

class RoleSerializers(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = '__all__' class RoleView(GenericViewSet):
queryset = models.Role.objects.all()
serializer_class = RoleSerializers def list(self, request, *args, **kwargs):
# 获取数据
obj = self.get_queryset()
# 序列化
ser = self.get_serializer(obj, many=True)
return Response(ser.data)

View

c. ModelViewSet

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):

urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^role/$', views.RoleView.as_view({'get': 'list', 'post': 'create'}), ),
url(r'^role/(?P<pk>)\d+/$', views.RoleView.as_view({'get': 'retrieve', 'delete': 'destroy', 'put': 'update', 'patch': 'partial_update'}), ), ]

urls

class RoleView(ModelViewSet):
queryset = models.Role.objects.all()
serializer_class = RoleSerializers

View

a. 增删改查 ModelViewSet

b. 增删 CreateModelMixin,DestroyModelMixin GenericViewSet

c. 复杂逻辑 GenericViewSet 或 APIView

路由

会自动生成增删改查等url

from django.conf.urls import url, include
from django.contrib import admin
from app01 import views
from rest_framework import routers router = routers.DefaultRouter()
router.register(r'role', views.RoleView) urlpatterns = [
url(r'^', include(router.urls)),
]

urls

认证

a.用户url传入的token认证

from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions class MyAuthentication(BasicAuthentication):
def authenticate(self, request):
token = request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed('Token认证失败')
else:
return token_obj.username, token_obj.token # 验证通过返回元祖,第一个参数和request.user是对应的,所以最好是用户名 class RoleView(ModelViewSet):
authentication_classes = [MyAuthentication, ]
queryset = models.Role.objects.all()
serializer_class = RoleSerializers

View

b.用户登录添加token

class RoleView(ModelViewSet):
authentication_classes = []
queryset = models.Role.objects.all()
serializer_class = RoleSerializers def post(self, request, *args, **kwargs):
res = {'state_code': 1000, 'msg': None}
try:
name = request._request.POST.get('username')
pwd = request._request.POST.get('password')
user = models.UserInfo.objects.filter(username=name, password=pwd).first()
if not user:
res["state_code"] = 1001 # 错误状态码
res["msg"] = "用户名或者密码错误"
else:
# 为用户创建token
token = md5(name)
# 存在就更新,否则就创建
models.UserToken.objects.update_or_create(user=user, defaults={'token': token})
res['token'] = token
except Exception as e:
res['state_code'] = 1002
res['msg'] = '请求异常'
return Response(res)

View

BasicAuthentication、SessionAuthentication、TokenAuthentication、JSONWebTokenAuthentication 都属于认证都继承BaseAuthentication,方法类似

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本认证
'rest_framework.authentication.SessionAuthentication', # session认证
)
}

Setting

权限

class MyPermission(BasePermission):
def has_permission(self, request, view):
message = '只有SVIP可以访问'
if request.user != 3:
return False
return True # 局部
permission_classes = [MyPermission, ]

View

频率

from rest_framework.throttling import SimpleRateThrottle

class VisitThrottle(SimpleRateThrottle):
# 配置文件中进行配置
scope = 'Luffy' def get_cache_key(self, request, view):
return self.get_ident(request) class UserThrottle(SimpleRateThrottle):
scope = 'LuffyUser' 局部
throttle_classes = [VisitThrottle, ]

View

REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {
"Luffy": '3/m',
"LuffyUser": '10/m',
}
}

Setting

版本

a.url的get传参方式

/user?version=v1

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1', # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version' # URL中获取值的key
}

setting

from rest_framework.versioning import QueryParameterVersioning

class TestView(APIView):
versioning_class = QueryParameterVersioning def get(self, request, *args, **kwargs): # 获取版本
print(request.version)
# 获取版本管理的类
print(request.versioning_scheme) # 反向生成URL
reverse_url = request.versioning_scheme.reverse('test', request=request)
print(reverse_url) return Response('GET请求,响应内容')

b.基于url正则表达式

/v1/user/

REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning'
'DEFAULT_VERSION': 'v1', # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version' # URL中获取值的key
}

setting

class TestView(APIView):
# 局部
versioning_class = URLPathVersioning def get(self, request, *args, **kwargs):
# 获取版本
print(request.version)
# 获取版本管理的类
print(request.versioning_scheme) # 反向生成URL
reverse_url = request.versioning_scheme.reverse('test', request=request)
print(reverse_url)

View

urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
]

urls

解析器

用于处理不同请求头数据

REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser']
}

setting

class ParserView(APIView):
# parser_classes = [JSONParser,FormParser,]
"""
JSONParser:表示只能解析content-type:application/json头
FormParser:表示只能解析content-type:application/x-www-form-urlencoded头
""" def post(self,request,*args,**kwargs):
"""
允许用户发送JSON格式数据
a. content-type: application/json
b. {'name':'alex',age:18}
:param request:
:param args:
:param kwargs:
:return:
"""
"""
1. 获取用户请求
2. 获取用户请求体
3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
4. JSONParser对象去请求体
5. request.data
"""
print(request.data) return HttpResponse('ParserView')

View

dispatch

  

rest_framwork组件的更多相关文章

  1. DRF框架之 serializers 序列化组件

    1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...

  2. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

  3. rest-framework框架的基本组件

    快速实例 Quickstart 大致步骤 (1)创建表,数据迁移 (2)创建表序列化类BookSerializer class BookSerializer(serializers.Hyperlink ...

  4. DRF-->2序列化组件的使用和接口设计--get,post,put,delete&优化组件

    !!!!! !!!!! 记住这个图 !!!!! 上篇博客说道DRF序列化组件的get,只是简单的举一个实例,然而在现实生活中我们前后端进行交互的时候更多的用到了Json数据格式,这也就是说前后端交互的 ...

  5. ExtJS 4.2 评分组件

    上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...

  6. react组件的生命周期

    写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...

  7. react-router 组件式配置与对象式配置小区别

    1. react-router 对象式配置 和 组件式配置    组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...

  8. Angular2入门系列教程3-多个组件,主从关系

    上一篇 Angular2项目初体验-编写自己的第一个组件 好了,前面简单介绍了Angular2的基本开发,并且写了一个非常简单的组件,这篇文章我们将要学会编写多个组件并且有主从关系 现在,假设我们要做 ...

  9. Angular2入门系列教程2-项目初体验-编写自己的第一个组件

    上一篇 使用Angular-cli搭建Angular2开发环境 Angular2采用组件的编写模式,或者说,Angular2必须使用组件编写,没有组件,你甚至不能将Angular2项目启动起来 紧接着 ...

随机推荐

  1. Python操作列表

    1.List Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示: >>> ...

  2. 树形dp学习

    学习博客:https://www.cnblogs.com/qq936584671/p/10274268.html 树的性质:n个点,n-1条边,任意两个点之间只存在一条路径,可以人为设置根节点,对于任 ...

  3. js循环里进行回调,引用循环里的变量,发现只是最后值的问题

    做项目的时候,栽在一个小地方,是这样的 我有很多个坐标点,我想把这些坐标点都绑定一个事件,当点击了这个坐标点之后,发送一个ajax 请求,将坐标点的id 发出去,等待显示返回的数据 但是实际当中,无论 ...

  4. Jersey前后端交互初体验

    一 get请求 前端 基本的GET请求 $.ajax({ type : "get", url : "../rest/api/account/delete", d ...

  5. nyoj 1216——整理图书 CF 229D—— Towers——————【dp+贪心】

    整理图书 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 小明是图书鹳狸猿,他有很多很多的书堆在了一起摆在了架子上,每摞书是横着放的,而且每摞书是订好的 是一个整体, ...

  6. 基于JQUERY 的图片查看插件

    viewer是一款功能强大的图片查看器.它可以实现ACDsee等看图软件的部分功能.它可以对图片进行移动,缩放,旋转,翻转,可以前后浏览一组图片.该图片查看器还支持移动设备,支持键盘控制,功能十分强大 ...

  7. XtraReport三动态数据绑定

    代码还用上一节的,把Report的Datasource去掉.各个绑定的字段也去掉,有了第二节的基础,现在看这个就不难了,无非就是传到report一个数据集,在把这个数据集绑定到各控件里 清空detai ...

  8. Java反射破坏单例模式

    今天电话面试的时候问到了,Google了一下 原出处: http://blog.csdn.net/lws332969674/article/details/8125893 一. Java中的反射技术可 ...

  9. ansible软件相关模块丶计划任务,剧本

    软件相关模块 yum rpm 和yum 的区别 rpm:redhat package manager yum可以解决依赖关系 yum 源配置 [epel] name=Extra Packages fo ...

  10. 织梦channelartlist标签内使用currentstyle

    找到文件\include\taglib\channelartlist.lib.php 找到代码 $pv->Fields['typeurl'] = GetOneTypeUrlA($typeids[ ...