REST framework---基於類的視圖

1、程序設計

1.路由設計html

from django.conf.urls import url
from django.contrib import admin
from app import views
from django.views import View

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    # 基於類的視圖
    url(r'^login/', views.LoginView.as_view()),
    url(r'^logout/', views.LogoutView.as_view()),

]

2.模型設計git

from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
    """
    用戶信息表
    """
    nid = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=11,
                             null=True,
                             unique=True,
                             )

    def __str__(self):
        return self.username

    class Meta:
        verbose_name = "用戶信息"
        verbose_name_plural = verbose_name

# 不要忘記在setting.py中引用Django的UserInfo表
# 引用Django自帶的UserInfo表,繼承使用時須要設置
AUTH_USER_MODEL = "app.UserInfo"   

3.視圖設計github

from django.views import View
class
LoginView(View): def get(self, request, *args, **kwargs): form_obj = forms.LoginForm() return render(request, "login.html", {"form_obj": form_obj},) def post(self, request, *args, **kwargs): ret = {"code": 0} # 獲取用戶輸入的用戶名、密碼 username = request.POST.get("username") password = request.POST.get("password") # 判斷用戶是否存在以及認證 user_obj = auth.authenticate(username=username, password=password) if user_obj: # 登陸 auth.login(request, user_obj) # 認證成功後可跳轉的地址 ret["data"] = "/index/" else: # 認證失敗 ret["code"] = 1 ret["data"] = "用戶名或密碼錯誤" return JsonResponse(ret) class LogoutView(View): # 退出登陸 def get(self, request, *args, **kwargs): auth.logout(request) return redirect("/login/")

2、View源碼解析

1.基於函數的視圖中,URL設計中,當接收到客戶端請求時根據正則匹配獲得相應的視圖函數並執行,而後獲得相應的HttpResponse響應django

url(r'^login/', views.login),

2.基於類的視圖中,最終也是將函數的執行結果返回給客戶端,不一樣的是當接收到客戶端請求時,根據類調用類中的方法,由類的繼承、封裝、多態、屬性查找等特性最終獲得相應的HttpResponse響應app

 url(r'^login/', views.LoginView.as_view()),

  看源碼(展現中將部分源碼省略):函數

  1)客戶端發起請求,省略前邊一系列中間件等流程,進行路由解析的時候,經過路由匹配拿到對應的類,發現post

拿到的是一個對象.屬性的方法,因而進行類的屬性查找網站

class LoginView(View):
    def get(self, request, *args, **kwargs):
        ...
    def post(self, request, *args, **kwargs):
        ...

  2)發現該視圖類中沒有 as_view() 這個方法,因而根據屬性查找關係到繼承的類View中查找url

class View(object):
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    @classonlymethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
            return self.dispatch(request, *args, **kwargs)
        return view

  3)函數中的self爲當前的訪問到的LoginView對象,在上面的view()方法中返回時遇到self.dispatch(),因而有通過一次屬性查找,子類中找不到又再次來到View父類中查找dispatch()方法,最終獲得如下spa

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)return handler(request, *args, **kwargs)

  4)最終經過反射的方式從View類定義的HTTP請求方法和類視圖LoginView中對應的方法,獲取到HttpResponse響應返回給客戶端

 

以上是Django中內置的類視圖方法,還能夠經過安裝restframework模塊,繼承其模塊內的APIView類實現:

  1)APIView實際上繼承的也是Django內置的View類

  2)獲取HttpResponse響應返回給客戶端的過程與以前解析的方法相同,區別在於通過屬性查找原則最終調用dispatch()方法時,調用的是REST framework內的自定義的dispatch()

    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

  經過屬性查找等規則,最後獲得一個HttpResponse相應,不一樣的是在使用REST famework模塊時,可在調用dispatch()方法時實現REST framework提供的其它功能

官方網站:

http://www.django-rest-framework.org/

第三方翻譯的中文文檔:

https://q1mi.github.io/Django-REST-framework-documentation/
相關文章
相關標籤/搜索