(了解)rest_framework之版本控制, 响应器, url控制器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(了解)rest_framework之版本控制, 响应器, url控制器相关的知识,希望对你有一定的参考价值。
参考技术A 本文均为了解点掌握的:URLPathVersioning
-局部使用:
versioning_class = URLPathVersioning
-全局使用:
路由配置:
在视图类中的request对象中,就可以取出版本号
反向解析:
rest_framework中用Response返回数据时, 默认返回给浏览器的是一个好看的页面,例如
url为: http://127.0.0.1:8000/book/ 时, 返回的是页面
如果不要返回页面, 而是只返回数据需要这样
http://127.0.0.1:8000/book/?format=json
自己指定返回啥
Python之Django rest_Framework
实例化:
v1 = ["view.xxx.path.Role","view.xxx.path.Group",] 可以循环,循环出来的每一个不能实例化
如果把v1循环弄成每一个对象列表,通过rsplit切割,在通过importlib.import_module拿到每一个路径,在通过getattr把它的类名拿过来,
这个类加括号就是实例化想
for item in v1:
m = importlib.import_module(\'view.xxx.path\')
cls = getattr(m,\'Role\')
cls()
from view.xxx.path import Role,Group
v2 = [Group,Role] 这个可以循环每一个实例化
for item in v2: #循环V2的每一个元素加括号,就是实例化
item()
rest_Framework的规范:
按顺序:它的method的不同,原来没有考虑,原来是url区分,现在通过method来区分,method的不同提交方式不同,紧接着一般是面向资源的就是把url变成名词,接下就是返回值,以前没有考虑状态码,现在有考虑状态码。(一般有get,post方法,还有put,delete等方法)
一、Django rest_Framework框架
----为什么用Django rest_Framework框架?
----首先没有Django rest_Framework框架用django也是可以做出来的,只不过它为我们提供一些API常用的功能,比如:(认证,权限,限流,有了这些我们只需要写个类已配置,它就能当都市图用,还能全局配置,如果自己写还得写中间件,写装饰器来实现,通过Django rest_Framework框架,他已经把规则写好,只需要写类,只需实现方法,返回值就可以)实现了一部分功能。
----设计比较好
----单独视图+全局配置 =>Dajngo中间件(importlib/反射)=>动态配置课扩展(短信,邮件,微信等提醒)
二、Django rest_Framework原理?
先开始在路由,路由.as_view:
点击as_view
请求进来,走完以上,才走self.dispatch()
走self.dispatch()流程如下地址:http://www.cnblogs.com/mengqingjian/p/8419563.html
三、版本
a.根据url的不同来来操作,版本控制
先在setting中注册
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ #url(r\'^admin/\', admin.site.urls), url(r\'^api/(?P<version>[v1|v2]+)/\', include(\'api.urls\')), # url(r\'^api/\', include(\'api.urls\')), url(r\'^backend/\', include(\'backend.urls\')), ]
REST_FRAMEWORK = { \'VERSION_PARAM\':\'version\', \'DEFAULT_VERSION\':\'v1\', \'ALLOWED_VERSIONS\':[\'v1\',\'v2\'], # \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.HostNameVersioning" \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.URLPathVersioning" }
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BasicAuthentication from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning,HostNameVersioning from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer class UsersView(APIView): # 基于url传参 # versioning_class = QueryParameterVersioning # 基于URL http://127.0.0.1:8001/api/v2/users/ # versioning_class = URLPathVersioning # 基于子域名 http://v1.luffy.com/users/ # versioning_class = HostNameVersioning def get(self,request,*args,**kwargs): self.dispatch # print(request.version) # QueryParameterVersioning().detemiin_version() # print(request.versioning_scheme) # QueryParameterVersioning() # 当前版本一样的URL # url = request.versioning_scheme.reverse(viewname=\'u\',request=request) # print(url) # 当前版本不一样的URL # from django.urls import reverse # url = reverse(viewname=\'u\',kwargs={\'version\':\'v2\'}) # print(url) return Response(\'...\')
from django.conf.urls import url,include from . import views urlpatterns = [ url(r\'^users/\', views.UsersView.as_view(),name=\'u\'), ]
b、
HostName
urlpatterns = [
#url(r\'^admin/\', admin.site.urls),
url(r\'^api/\', include(\'api.urls\')),
]
urlpatterns = [
url(r\'^users/\', views.UsersView.as_view(),name=\'u\'),
]
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
print(request.version) # QueryParameterVersioning().detemiin_version()
print(request.versioning_scheme) # QueryParameterVersioning()
REST_FRAMEWORK = {
\'VERSION_PARAM\':\'version\',
\'DEFAULT_VERSION\':\'v1\',
\'ALLOWED_VERSIONS\':[\'v1\',\'v2\'],
\'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.HostNameVersioning"
}
# C:\\Windows\\System32\\drivers\\etc
# vim /etc/hosts
127.0.0.1 v1.luffy.com
127.0.0.1 v2.luffy.com
四、rest framework解析器
请求的数据进行解析:请求体进行解析。表示服务端可以解析的数据格式的种类。
Content-Type: application/url-encoding.....
request.body
request.POST
Content-Type: application/json.....
request.body
request.POST
客户端:
Content-Type: application/json
\'{"name":"alex","age":123}\'
服务端接收:
读取客户端发送的Content-Type的值 application/json
parser_classes = [JSONParser,]
media_type_list = [\'application/json\',]
如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
配置:
单视图:
class UsersView(APIView):
parser_classes = [JSONParser,]
全局配置:
REST_FRAMEWORK = {
\'VERSION_PARAM\':\'version\',
\'DEFAULT_VERSION\':\'v1\',
\'ALLOWED_VERSIONS\':[\'v1\',\'v2\'],
# \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.HostNameVersioning"
\'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.URLPathVersioning",
\'DEFAULT_PARSER_CLASSES\':[
\'rest_framework.parsers.JSONParser\',
\'rest_framework.parsers.FormParser\',
]
}
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ #url(r\'^admin/\', admin.site.urls), url(r\'^api/(?P<version>[v1|v2]+)/\', include(\'api.urls\')), # url(r\'^api/\', include(\'api.urls\')), url(r\'^backend/\', include(\'backend.urls\')), ]
REST_FRAMEWORK = { \'VERSION_PARAM\':\'version\', \'DEFAULT_VERSION\':\'v1\', \'ALLOWED_VERSIONS\':[\'v1\',\'v2\'], # \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.HostNameVersioning" \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.URLPathVersioning", \'DEFAULT_PARSER_CLASSES\':[ \'rest_framework.parsers.JSONParser\', \'rest_framework.parsers.FormParser\', ] }
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BasicAuthentication from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning,HostNameVersioning from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer from rest_framework.parsers import JSONParser,FormParser from rest_framework.request import Request class UsersView(APIView): def get(self,request,*args,**kwargs): self.dispatch return Response(\'...\') def post(self,request,*args,**kwargs): # # application/json # print(request._request.body) # b"xxxxx" decode() json.loads # print(request._request.POST) # 无 # # # www-form-url-encode # print(request._request.body) # print(request._request.POST) # print(request.data) # print(request.POST) # print(request.FILES) request.data return Response(\'...\')
from django.conf.urls import url,include from . import views urlpatterns = [ url(r\'^users/\', views.UsersView.as_view(),name=\'u\'), ]
五、 rest framework序列化+Form
序列化:
对象 -> 字符串 序列化
字符串 -> 对象 反序列化
目的:
解决QuerySet序列化问题
序列化:
a、基本操作
class UsersSerializer(serializers.Serializer):
name = serializers.CharField()
pwd = serializers.CharField()
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
# return Response(user_list)
# 方式二之多对象
# user_list = models.UserInfo.objects.all()
# ser = UsersSerializer(instance=user_list,many=True)
# return Response(ser.data)
# 方式二之单对象
user = models.UserInfo.objects.all().first()
ser = UsersSerializer(instance=user, many=False)
return Response(ser.data)
b、跨表
class UsersSerializer(serializers.Serializer): name = serializers.CharField() pwd = serializers.CharField() group_id = serializers.CharField() xxxx = serializers.CharField(source="group.title") x1 = serializers.CharField(source="group.mu.name") class UsersView(APIView): def get(self,request,*args,**kwargs): self.dispatch # 方式一: # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title") # return Response(user_list) # 方式二之多对象 user_list = models.UserInfo.objects.all() ser = UsersSerializer(instance=user_list,many=True) return Response(ser.data)
c、复杂序列化
解决方案一:
class MyCharField(serializers.CharField):
def to_representation(self, value):
data_list = []
for row in value:
data_list.append(row.name)
return data_list
class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # obj.mu.name
x2 = MyCharField(source="roles.all") # obj.mu.name
解决方案二:
class MyCharField(serializers.CharField):
def to_representation(self, value):
return {\'id\':value.pk, \'name\':value.name}
class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # obj.mu.name
x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
解决方案三(*):
class UsersSerializer(serializers.Serializer):
name = serializers.CharField() # obj.name
pwd = serializers.CharField() # obj.pwd
group_id = serializers.CharField() # obj.group_id
xxxx = serializers.CharField(source="group.title") # obj.group.title
x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
# x2 = serializers.CharField(source="roles.all") # obj.mu.name
# x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
x2 = serializers.SerializerMethodField()
def get_x2(self,obj):
obj.roles.all()
role_list = obj.roles.filter(id__gt=1)
data_list = []
for row in role_list:
data_list.append({\'pk\':row.pk,\'name\':row.name})
return data_list
以上三种都是使用相同的视图:
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
# return Response(user_list)
# 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True)
return Response(ser.data)
d. 基于Model
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
# fields = [\'name\', \'pwd\',\'group\']
depth = 1
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
# return Response(user_list)
# 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True)
return Response(ser.data)
e. 生成URL
class UsersSerializer(serializers.ModelSerializer):
group = serializers.HyperlinkedIdentityField(view_name=\'detail\')
class Meta:
model = models.UserInfo
fields = "__all__"
fields = [\'name\', \'pwd\',\'group\']
depth = 1
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
# return Response(user_list)
# 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True,context={\'request\':request})
return Response(ser.data)
f. 全局生成URL
class UsersSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
# fields = [\'id\',\'name\',\'pwd\']
class UsersView(APIView):
def get(self,request,*args,**kwargs):
self.dispatch
# 方式一:
# user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
# return Response(user_list)
# 方式二之多对象
user_list = models.UserInfo.objects.all()
# [obj1,obj2,obj3]
ser = UsersSerializer(instance=user_list,many=True,context={\'request\':request})
return Response(ser.data)
请求数据验证:
a、
class PasswordValidator(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if value != self.base:
message = \'用户输入的值必须是 %s.\' % self.base
raise serializers.ValidationError(message)
def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 执行验证之前调用,serializer_fields是当前字段对象
pass
class UsersSerializer(serializers.Serializer):
name = serializers.CharField(min_length=6)
pwd = serializers.CharField(error_messages={\'required\': \'密码不能为空\'}, validators=[PasswordValidator(\'666\')])
b、
class PasswordValidator(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if value != self.base:
message = \'用户输入的值必须是 %s.\' % self.base
raise serializers.ValidationError(message)
def set_context(self, serializer_field):
"""版本,认证,权限