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/
  • 相关阅读:
    链表面试题Java实现【重要】
    数据结构Java实现05----栈:顺序栈和链式堆栈
    数据结构Java实现06----中缀表达式转换为后缀表达式
    数据结构Java实现07----队列:顺序队列&顺序循环队列、链式队列、顺序优先队列
    栈和队列的面试题Java实现,Stack类继承于Vector这两个类都不推荐使用
    MySQL多表查询之外键、表连接、子查询、索引
    MySQL字符串函数、日期时间函数
    sqlplus登录、连接命令
    LeetCode 68 Text Justification
    cocos2d触摸事件处理机制(2.x和3.x变化)
  • 原文地址:https://www.cnblogs.com/mdzzbojo/p/9395661.html
Copyright © 2011-2022 走看看