rest_Framework的規範: 按順序:它的method的不同,原來沒有考慮,原來是url區分,現在通過method來區分,method的不同提交方式不同,緊接著一般是面向資源的就是把url變成名詞,接下就是返回值,以前沒有考慮狀態碼,現在有考慮狀態碼。(一般有get,post方法,還有put ...
實例化:
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中註冊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')), ]url
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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" }settings.py配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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('...')views.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.conf.urls import url,include from . import views urlpatterns = [ url(r'^users/', views.UsersView.as_view(),name='u'), ]url.py -----和view在一個APP中的路由
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',
]
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')), ]url.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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', ] }setting.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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('...')views.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.conf.urls import url,include from . import views urlpatterns = [ url(r'^users/', views.UsersView.as_view(),name='u'), ]url.py 和view一個APP下的文件
五、 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):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 執行驗證之前調用,serializer_fields是當前欄位對象
pass
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
extra_kwargs = {
'name': {'min_length': 6},
'pwd': {'validators': [PasswordValidator(666), ]}
}
使用:
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)
def post(self,request,*args,**kwargs):
ser = UsersSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('...')