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项目启动起来 紧接着 ...
随机推荐
- cout和printf不能混用
1.两者的缓存机制不同:printf无缓冲区,而std::cout有 (其实printf也是有缓冲区的,https://blog.csdn.net/ithzhang/article/details/6 ...
- Collections练习之按照字符串长度进行排序
不多说,直接上干货! 代码需求 想从 [abcde, cba, aa, zzz, cba, nbaa] 变成 [aa, cba, cba, zzz, nbaa, abcde] CollectionsD ...
- 几个单元素Loading动画解构
这个账号建了也有1个多月,拖延症患者终于下定决心开始写博.做前端从前至后差不多1年时间,如果文中有什么纰漏欢迎指出,未来的路还很长~ 第一篇文章用来解构几个挺不错的单元素Loading动画.效果图如下 ...
- Prestashop后台模块(中英转译)
=======================Prestashop-Modules========================= Pretashop运行起来非常慢,这个大家应该都知道,最近要给这个 ...
- python 在windows下监听键盘按键
python 在windows下监听键盘按键 使用到的库 ctypes(通过ctypes来调用Win32API, 主要就是调用钩子函数) 使用的Win32API SetWindowsHookEx(), ...
- 解决navicate 连接mysql数据库中文乱码的问题
以下均是ubuntu12.04为准 1.修改mysql的配置文件. 1.1.vi /etc/mysql/my.conf找到[client]在其下面添加 default-character-set=u ...
- node搭环境
node是javascript的运行环境,npm是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等). 一.安装node 1.在https://nodejs.org/en/do ...
- DIV+CSS图片不间断滚动jquery特效(Marquee插件)及移动标签marquee整理
推荐一个jQuery的无缝文字滚动效果,同时也可以滚动图片,也叫做跑马灯效果. 此jquery插件,依托jquery库,能实现各种滚动效果,且让HTML代码符合W3C标准. marquee标签:创建一 ...
- 在项目引用里添加上对Microsoft Word 11.0 object library的引用
private void button1_Click(object sender, System.EventArgs e) { //调用打开文件对话框获取要打开的文件WORD文件,RTF文件,文本文件 ...
- SSRS 参数 单选 多选
前段时间 公司要求报表的选项可以多选. 知道需求后,研究了下实现. 首先我们创建一个报表,然后添加3个数据集,2个参数,如下图. DataSet1数据集:存放主数据. ddl_emplid数据集:存放 ...