django學習之django restful framework(一)


在學習django restful framework之前我們要先回顧一下:

1. 開發模式

- 普通開發方式(之前我們在開發的時候前后端放在一起寫,也就是說一個人會負責前端和后端的代碼,這樣就會導致開發的效率較低,而且如果后端開發人員的前端基礎較差的話,就會導致產品的質量不是很好)
- 前后端分離(前端人員做前端,VUE,后端的人員寫后端的代碼,因為很多的時候通過vue都是通過json數據進行傳輸的,因此作為后端的人員只需要將自己的數據通過json序列化之后就可以了)

2. 后端開發
為前端提供URL(API/接口的開發)
注:永遠返回HttpResponse(通過json的形式)

3. Django FBV、CBV
        FBV,function base view
            def users(request):
                user_list = ['alex','oldboy']
                return HttpResponse(json.dumps((user_list)))
                
        CBV,class base view 
            路由:
                url(r'^students/', views.StudentsView.as_view()),
            
            視圖:
                from django.views import View

                class StudentsView(View):

                    def get(self,request,*args,**kwargs):
                        return HttpResponse('GET')

                    def post(self, request, *args, **kwargs):
                        return HttpResponse('POST')

                    def put(self, request, *args, **kwargs):
                        return HttpResponse('PUT')

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse('DELETE')

ps:學會使用postman來模擬post請求

4. 列表生成式
class Foo:
pass

class Bar:
pass

v = []
for i in [Foo,Bar]:# 循環每個類
obj = i()# 類加括號實例化
v.append(obj)# 因此v里面就會有兩個類的實例化對象

v = [item() for item in [Foo,Bar]] # 列表生成式
v其實就是一個對象列表

5. 面向對象基礎知識

- 封裝
            - 對同一類方法封裝到類中
                class File:
                    文件增刪改查方法
                    
                Class DB:
                    數據庫的方法
                    
            - 將數據封裝到對象中
                class File:
                    def __init__(self,a1,a2):
                        self.a1 = a1 
                        self.xxx = a2
                    def get:...
                    def delete:...
                    def update:...
                    def add:...
                    
                obj1 = File(123,666)
                obj2 = File(456,999)
        
            PS: 擴展 
                class Request(object):

                    def __init__(self,obj):
                        self.obj = obj

                    @property
                    def user(self):
                        return self.obj.authticate()

                class Auth(object):
                    def __init__(self,name,age):
                        self.name = name
                        self.age = age

                    def authticate(self):
                        return self.name


                class APIView(object):

                    def dispatch(self):
                        self.f2()

                    def f2(self):
                        a = Auth('alex',18)
                        b = Auth('oldboy',18)
                        req = Request(b)
                        print(req.user)

                obj = APIView()
                obj.dispatch()

 6.CVB形式的源碼分析

1.因為每個url對應的都是一個函數,也就是一個視圖當代碼運行到url(r'^students/', views.StudentsView.as_view())這里的時候其實就是返回一個視圖,通過as_view->view返回一個視圖函數
2.def as_view(cls, **initkwargs)-->def view(request, *args, **kwargs);當執行self = cls(**initkwargs)這句話的時候,cls加括號也就是實例化這個類,等價於:self = StudentsView()
3.下面就會執行return self.dispatch(request, *args, **kwargs)中的dispatch方法;換個方式:ret = self.dispatch(request, *args, **kwargs),return ret 也就是執行StudentsView里面的dispatch方法;執行dispatch是有返回值的,返回的值就是Httpresponse以及render,redreit等等;換句話說也就是請求進來之后直接執行dispatch,無論是什么請求進來都會執行dispatch
    def dispatch(self, request, *args, **kwargs):
        func = getattr(self, request.method.lower()) #通過反射拿到請求方式然后轉成小寫
        ret = func(request, *args, **kwargs)# 執行函數
        return ret
4.在源碼中如何實現的呢?
    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

FBV、CBV筆記說明:
CBV,基於反射實現根據請求方式不同,執行不同的方法。
原理:
url -> view方法 -> dispatch方法(反射執行其他:GET/POST/DELETE/PUT)

如果這樣寫呢?執行父類的方法

流程:
class StudentsView(View):
def dispatch(self, request, *args, **kwargs):
print('before')
ret = super(StudentsView,self).dispatch(request, *args, **kwargs)
print('after')
return ret

def get(self,request,*args,**kwargs):
return HttpResponse('GET')

def post(self, request, *args, **kwargs):
return HttpResponse('POST')

def put(self, request, *args, **kwargs):
return HttpResponse('PUT')

def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE')

流程:

1.請求一進來先執行dispatch方法,然后執行父類的dispatch方法

2.里面的self指的是StudentsView,然后父類里面的handler = getattr(self, request.method.lower(), self.http_method_not_allowed)的self也是StudentsView,最后返回Httpresponse對象,然后將ret返回

繼承:

 1 繼承(多個類共用的功能,為了避免重復編寫):
 2             from django.views import View
 3 
 4 
 5             class MyBaseView(object):
 6                 def dispatch(self, request, *args, **kwargs):
 7                     print('before')
 8                     ret = super(MyBaseView,self).dispatch(request, *args, **kwargs)
 9                     print('after')
10                     return ret
11 
12             class StudentsView(MyBaseView,View):
13 
14                 def get(self,request,*args,**kwargs):
15                     print('get方法')
16                     return HttpResponse('GET')
17 
18                 def post(self, request, *args, **kwargs):
19                     return HttpResponse('POST')
20 
21                 def put(self, request, *args, **kwargs):
22                     return HttpResponse('PUT')
23 
24                 def delete(self, request, *args, **kwargs):
25                     return HttpResponse('DELETE')
26 
27             class TeachersView(MyBaseView,View):
28 
29                 def get(self,request,*args,**kwargs):
30                     return HttpResponse('GET')
31 
32                 def post(self, request, *args, **kwargs):
33                     return HttpResponse('POST')
34 
35                 def put(self, request, *args, **kwargs):
36                     return HttpResponse('PUT')
37 
38                 def delete(self, request, *args, **kwargs):
39                     return HttpResponse('DELETE')
View Code

7.csrf補充

7.1. django中間件
- process_request
- process_view
- process_response
- process_exception
- process_render_template

當請求到來的時候,先是執行process_request,然后再執行process_view,再進入視圖函數

7.2. 使用中間件做過什么?
- 權限
- 用戶登錄驗證
- django的csrf是如何實現?
    是放在process_view方法里面的:

如果加上from django.views.decorators.csrf import csrf_exempt,csrf_exempt免除csrf驗證

- 檢查視圖是否被 @csrf_exempt (免除csrf認證)
- 去請求體或cookie中獲取token

7.3:FBV

                情況一:
                    MIDDLEWARE = [
                        'django.middleware.security.SecurityMiddleware',
                        'django.contrib.sessions.middleware.SessionMiddleware',
                        'django.middleware.common.CommonMiddleware',
                        'django.middleware.csrf.CsrfViewMiddleware', # 全站使用csrf認證
                        'django.contrib.auth.middleware.AuthenticationMiddleware',
                        'django.contrib.messages.middleware.MessageMiddleware',
                        'django.middleware.clickjacking.XFrameOptionsMiddleware',
                    ]
                    
                    
                    from django.views.decorators.csrf import csrf_exempt
                    @csrf_exempt # 該函數無需認證
                    def users(request):
                        user_list = ['alex','oldboy']
                        return HttpResponse(json.dumps((user_list)))
                
                情況二:
                    MIDDLEWARE = [
                        'django.middleware.security.SecurityMiddleware',
                        'django.contrib.sessions.middleware.SessionMiddleware',
                        'django.middleware.common.CommonMiddleware',
                        #'django.middleware.csrf.CsrfViewMiddleware', # 全站不使用csrf認證
                        'django.contrib.auth.middleware.AuthenticationMiddleware',
                        'django.contrib.messages.middleware.MessageMiddleware',
                        'django.middleware.clickjacking.XFrameOptionsMiddleware',
                    ]
                    
                    
                    from django.views.decorators.csrf import csrf_exempt
                    @csrf_protect # 該函數需認證
                    def users(request):
                        user_list = ['alex','oldboy']
                        return HttpResponse(json.dumps((user_list)))

7.4:CBV

CBV小知識,csrf時需要使用
- @method_decorator(csrf_exempt)
- 在dispatch方法中(單獨方法無效)

方式一:
                from django.views.decorators.csrf import csrf_exempt,csrf_protect
                from django.utils.decorators import method_decorator
                class StudentsView(View):
                    
                    @method_decorator(csrf_exempt)
                    def dispatch(self, request, *args, **kwargs):
                        return super(StudentsView,self).dispatch(request, *args, **kwargs)

                    def get(self,request,*args,**kwargs):
                        print('get方法')
                        return HttpResponse('GET')

                    def post(self, request, *args, **kwargs):
                        return HttpResponse('POST')

                    def put(self, request, *args, **kwargs):
                        return HttpResponse('PUT')

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse('DELETE')
            方式二:
                from django.views.decorators.csrf import csrf_exempt,csrf_protect
                from django.utils.decorators import method_decorator

                @method_decorator(csrf_exempt,name='dispatch')
                class StudentsView(View):

                    def get(self,request,*args,**kwargs):
                        print('get方法')
                        return HttpResponse('GET')

                    def post(self, request, *args, **kwargs):
                        return HttpResponse('POST')

                    def put(self, request, *args, **kwargs):
                        return HttpResponse('PUT')

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse('DELETE')

8.restful 規范(建議)

a. 接口開發
            
            urlpatterns = [
                # url(r'^admin/', admin.site.urls),
                url(r'^get_order/', views.get_order),
                url(r'^add_order/', views.add_order),
                url(r'^del_order/', views.del_order),
                url(r'^update_order/', views.update_order),
            ]
            
                
            def get_order(request):
                return HttpResponse('')


            def add_order(request):
                return HttpResponse('')


            def del_order(request):
                return HttpResponse('')


            def update_order(request):
                return HttpResponse('')

這樣就會出現一個小問題,url會越來越多,不好維護

b. restful 規范(建議)
            
            1. 根據method不同做不同的操作,示例:
            
                基於FBV:
                    urlpatterns = [
                        url(r'^order/', views.order),
                    ]

                    def order(request):
                        if request.method == 'GET':
                            return HttpResponse('獲取訂單')
                        elif request.method == 'POST':
                            return HttpResponse('創建訂單')
                        elif request.method == 'PUT':
                            return HttpResponse('更新訂單')
                        elif request.method == 'DELETE':
                            return HttpResponse('刪除訂單')
                基於CBV:
                    urlpatterns = [
                        url(r'^order/', views.OrderView.as_view()),
                    ]
            
                    class OrderView(View):
                        def get(self,request,*args,**kwargs):
                            return HttpResponse('獲取訂單')

                        def post(self,request,*args,**kwargs):
                            return HttpResponse('創建訂單')

                        def put(self,request,*args,**kwargs):
                            return HttpResponse('更新訂單')

                        def delete(self,request,*args,**kwargs):
                            return HttpResponse('刪除訂單')

get:獲取;delete:刪除;post:創建;put:更新

 

9.安裝:django rest framework框架

源碼分析:cbv

1.當請求進來的時候首先會通過url對應一個函數,對於cbv的方式先會調用按時as_view,再去調用view方法返回對應的視圖函數,最重要的是里面的dispatch方法

2.

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

在這個方法中首先request = self.initialize_request(request, *args, **kwargs),在initialize_request這個方法中封裝了一個Request

 return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

這里面的request是原生的request,里面的authenticators返回的是一個對象列表:接下來我們進入get_authenticators()這個方法中去:return [auth() for auth in self.authentication_classes],返回的是一個列表生成式,也就是認證類的對象

因此執行了request = self.initialize_request(request, *args, **kwargs)這句話之后,那么這個request是一個全新的request,豐富了原生的request的內容

接下來就會執行self.initial(request, *args, **kwargs)這個方法,再去執行self.perform_authentication(request)這個方法,將新的request放入這個方法去處理:返回的是request.user

我們再看user里面是做了些什么:

    def _authenticate(self):
        """
        Attempt to authenticate the request using each authentication instance
        in turn.
        """
        for authenticator in self.authenticators:
            try:
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                return

        self._not_authenticated()

通過for authenticator in self.authenticators:這個循環取到認證類的對象,然后一個個的認證,最后返回一個request.user

代碼示例:

 1 - 僅使用:
 2                     from django.views import View
 3                     from rest_framework.views import APIView
 4                     from rest_framework.authentication import BasicAuthentication
 5                     from rest_framework import exceptions
 6                     from rest_framework.request import Request
 7 
 8                     class MyAuthentication(object):
 9                         def authenticate(self,request):
10                             token = request._request.GET.get('token')
11                             # 獲取用戶名和密碼,去數據校驗
12                             if not token:
13                                 raise exceptions.AuthenticationFailed('用戶認證失敗')
14                             return ("alex",None)
15 
16                         def authenticate_header(self,val):
17                             pass
18 
19                     class DogView(APIView):
20                         authentication_classes = [MyAuthentication,]
21 
22                         def get(self,request,*args,**kwargs):
23                             print(request)
24                             print(request.user)
25                             ret  = {
26                                 'code':1000,
27                                 'msg':'xxx'
28                             }
29                             return HttpResponse(json.dumps(ret),status=201)
30 
31                         def post(self,request,*args,**kwargs):
32                             return HttpResponse('創建Dog')
33 
34                         def put(self,request,*args,**kwargs):
35                             return HttpResponse('更新Dog')
36 
37                         def delete(self,request,*args,**kwargs):
38                             return HttpResponse('刪除Dog')
View Code

 


免責聲明!

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



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