Python之Django rest_Framework(2)


實例化: 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')),
]
url

 

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配置
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
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', ] }
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
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
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
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('...')

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM