zoukankan      html  css  js  c++  java
  • REST framework-基于类的视图

    一、程序设计

    1.路由设计

    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.模型设计

    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.视图设计

    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/")

    二、View源码解析

    1.基于函数的视图中,URL设计中,当接收到客户端请求时根据正则匹配得到相应的视图函数并执行,然后得到相应的HttpResponse响应

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

    2.基于类的视图中,最终也是将函数的执行结果返回给客户端,不同的是当接收到客户端请求时,根据类调用类中的方法,由类的继承、封装、多态、属性查找等特性最终得到相应的HttpResponse响应

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

      看源码(展示中将部分源码省略):

      1)客户端发起请求,省略前边一系列中间件等流程,进行路由解析的时候,通过路由匹配拿到对应的类,发现

    拿到的是一个对象.属性的方法,于是进行类的属性查找

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

      2)发现该视图类中没有 as_view() 这个方法,于是根据属性查找关系到继承的类View中查找

    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()方法,最终得到以下

    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/
  • 相关阅读:
    POJ 2240 Arbitrage spfa 判正环
    POJ 3259 Wormholes spfa 判负环
    POJ1680 Currency Exchange SPFA判正环
    HDU5649 DZY Loves Sorting 线段树
    HDU 5648 DZY Loves Math 暴力打表
    HDU5647 DZY Loves Connecting 树形DP
    CDOJ 1071 秋实大哥下棋 线段树
    HDU5046 Airport dancing links 重复覆盖+二分
    HDU 3335 Divisibility dancing links 重复覆盖
    FZU1686 神龙的难题 dancing links 重复覆盖
  • 原文地址:https://www.cnblogs.com/mdzzbojo/p/9395661.html
Copyright © 2011-2022 走看看