rest_framwork组件
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组件的更多相关文章
- DRF框架之 serializers 序列化组件
1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...
- DRF 视图组件,路由组件
视图组件 -- 第一次封装 -- GenericAPIView(APIView): queryset = None serializer_class = None def ge ...
- rest-framework框架的基本组件
快速实例 Quickstart 大致步骤 (1)创建表,数据迁移 (2)创建表序列化类BookSerializer class BookSerializer(serializers.Hyperlink ...
- DRF-->2序列化组件的使用和接口设计--get,post,put,delete&优化组件
!!!!! !!!!! 记住这个图 !!!!! 上篇博客说道DRF序列化组件的get,只是简单的举一个实例,然而在现实生活中我们前后端进行交互的时候更多的用到了Json数据格式,这也就是说前后端交互的 ...
- ExtJS 4.2 评分组件
上一文章是扩展ExtJS自带的Date组件.在这里将创建一个评分组件. 目录 1. 介绍 2. 示例 3. 资源下载 1. 介绍 代码参考的是 Sencha Touch 2上的一个RatingStar ...
- react组件的生命周期
写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...
- react-router 组件式配置与对象式配置小区别
1. react-router 对象式配置 和 组件式配置 组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...
- Angular2入门系列教程3-多个组件,主从关系
上一篇 Angular2项目初体验-编写自己的第一个组件 好了,前面简单介绍了Angular2的基本开发,并且写了一个非常简单的组件,这篇文章我们将要学会编写多个组件并且有主从关系 现在,假设我们要做 ...
- Angular2入门系列教程2-项目初体验-编写自己的第一个组件
上一篇 使用Angular-cli搭建Angular2开发环境 Angular2采用组件的编写模式,或者说,Angular2必须使用组件编写,没有组件,你甚至不能将Angular2项目启动起来 紧接着 ...
随机推荐
- java lamda
// 查询数据模拟 List<SealListViewVo> list = new ArrayList<SealListViewVo>(); for (int i = 0; i ...
- 性能测试工具LoadRunner09-LR之Virtual User Generator 日志
在录制和回放的时候,VU会分别把发生的事件记录成日志文件,这些日志有利于我们跟踪VU和服务器的交互过程 回放日志(Replay Log) 脚本回放运行时的输出都记在这个Log里 “输出”窗口的“回放日 ...
- (转)linux passwd批量修改用户密码
linux passwd批量修改用户密码 原文:http://blog.csdn.net/xuwuhao/article/details/46618913 对系统定期修改密码是一个很重要的安全常识, ...
- 通过进入单用户模式解决linux中的rc.local修改后无法启动的问题
问题:本想将teamviewer这个软件随linux自启动,所以将其启动命令放在rc.local中,但是重启后发现linux启动不起来了,系统前面都是正常启动的,就是无法进入帐户登陆界面,无法输入ro ...
- Oracle安装后忘记用户名或密码+创建新登陆用户
新安装的Oracle11g,不料在使用的时候没记住安装时的用户名和密码. 不用担心,打开sqlplus. 按如下步骤,新建一个登陆用户: 第一步:以sys登陆 sys/密码 as sysdba 此 ...
- httpd编译安装php
wget http://hk1.php.net/distributions/php-5.6.31.tar.gz yum groupinstall "Development Tools&quo ...
- REST与DDD
之前在为什么要使用MVC+REST+CQRS架构我曾经提出DDD是核心,REST是壳的观点,我想在这里详细谈谈我的思路. 今天正好看看到老外一篇博文Why REST is so important:按 ...
- [转]在离线环境中发布.NET Core至Windows Server 2008
本文转自:http://www.cnblogs.com/durow/p/5765145.html 0x00 写在开始 之前一篇博客中写了在离线环境中使用.NET Core,之后一边学习一边写了一些页面 ...
- Oracle数据库分割字符串function方法
下面我直接上传一串代码源码, create or replace function strsplit(p_value varchar2, p_split varchar2 := ',') --usag ...
- vueHistory 模式下,布置到服务器上路由刷新会报nginx404错误
之前写完vue项目后,布置到服务器,用nginx反向代理后,一开始进去,进各种路由都是没问题的,但是一旦f5刷新后就会出现一个nginx404的错误. 经过翻阅vue文档后,发现这是vueHistor ...