django学习第二天

django视图系统

request对象

  • 常用属性和方法
      print(request) #wsgirequest对象  
      print(request.path) #请求路径 /index/  
      print(request.method) #请求方法  POST GET
      print(request.POST) #post请求提交的数据<QueryDict:{'username':['root']}>  
      print(request.GET) #获取url中的查询参数 路径后面?a=1&b=1 返回 <QueryDict:{'a':['1'],'b':['2']}> 不是针对get请求的  
      print(request.body) #获取http请求消息格式的请求数据部分的内容  bytes类型 b''  
      print(request.META) #请求头信息  
      print(request.get_full_path()) #获取完整路径(包含查询参数) /index/?a=1  
      print(request.FILES) #上传的文件对象数据  
      print(request.FILES.get('file')) #返回文件对象  获取文件名可以用文件对象.name  
      #注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
   包含数据。否则,FILES 将为一个空的类似于字典的对象。  
      print(request.POST.get('username')) #获取键对应的值  
      print(request.GET.get('sex')) # 获取键对应的值  
      #多选提交来的数据通过getlist来获取
      print(request.POST.getlist('hobby')) #['2','3']

response响应

常用方法

      from django.shortcuts import render,HttpResponse,redirect  
      return HttpResponse('你好') #回复字符串   
      return render(request,'home.html') #回复html页面   
      #重定向方法,参数是个路径  
      return redirect('/home/') #封装了302状态码,以及浏览器要重定向的路径

添加响应头键值对

      ret = render(request,'home.html')  
      ret['a'] = 'b' #添加响应头键值对  
      return ret  

添加响应状态码

      ret = render(request,'home.html',status=202)#render修改状态码还可以这样改  
      ret.status_code = 201 #添加响应状态码  
      return ret #回复html页面  

CBV和FBV

  • 两种视图逻辑的写法方法
      FBV:全称function based view,就是基于函数来写视图逻辑
      CBV:全称class based view,就是基于类来写视图
  • 基于函数的写法
      urls.py写法
      url(r'^index/(d+)',views.index)

      views.py写法
      def index(request,xx):
            if request.method == 'get':
                  return render(request,'index.html')
            elif rquest.method == 'post':
                  return HttpResponse('你好')
  • 基于类的视图写法
      urls.py文件写法
      #类视图的url
      url(r'^login/',views.LoginView.as_view())

      views.py文件写法
      #需要导入View这个类,然后继承View这个类
      from django.views import View
      #登录需求
      class LoginView(View):  #继承这个View父类
            #get请求  获取login页面
            def get(self,request):
                  return render(request,'login.html')
            
            #post请求,获取post请求提交的数据,并校验等
            def post(self,request):
                  print(request.POST)
                  #<QueryDict:{'uname',['wei'],'pwd':['123']}>
                  return render(request,'login.html')

CBV源码重点(反射)

      from django.views import View
      View里面的dispatch方法中的反射逻辑,实现了不同的请求方法,找到我们视图类中的对应方法执行
      #源码如下:
    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
        #http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

    def http_method_not_allowed(self, request, *args, **kwargs):
        logger.warning(
            'Method Not Allowed (%s): %s', request.method, request.path,
            extra={'status_code': 405, 'request': request}
        )
        return http.HttpResponseNotAllowed(self._allowed_methods())

FBV和CBV加装饰器

  • FBV和普通函数加装饰方式一样
      #装饰器函数
      def outer(f):
            def inner(request,*args,**kwargs):
                  print('执行之前做的事')
                  ret = f(request,*args,**kwargs)
                  print('执行之后做的事')
                  return ret
            return inner
  #使用装饰器
      @outer
      def books(request):
            print('FBV执行了')
            return HttpResponse('OK')
  • CBV加装饰器
      from django.utils.decorators import method_decorator #加装饰器需要导入这个类
      from django.views import View  #类视图需要导入这个View类,并继承这个父类

      #装饰器函数
      def outer(f):
            def inner(request,*args,**kwargs):
                  print('执行之前')
                  ret = f(request,*args,**kwargs)
                  print('执行之后')
                  return ret
            return inner
      # 方法一 在每个方法上加装饰器
      class LoginView(View):
          @method_decorator(outer)
          def get(self,request):
              print('get方法')
              return render(request,'home.html')

          @method_decorator(outer)
          def post(self,request):
              print('post方法')
              return HttpResponse('ok')


      方法二:统一加一个装饰器
      class LoginView(View):
          # 给类方法统一加装饰器,借助dispatch方法(父类的dispatch方法,
          # 就是通过反射来完成不同的请求方法找到并执行我们自己定义的视图类的对应方法)
          @method_decorator(outer)
          def dispatch(self, request, *args, **kwargs):
              print('调用方法之前')
              ret = super().dispatch(request,*args,**kwargs) #重写父类的方法  返回的结果就是调用下面的get 或 post方法
              print('调用方法之后')
              return ret

          def get(self,request):
              print('get方法执行啦')
              return render(request,'home.html')

          def post(self,request):
              print('post方法执行啦')
              return HttpResponse('ok')
      执行顺序:get方法和post方法
      执行之前
      调用方法之前
      get方法执行啦
      调用方法之后
      执行之后



      #方法三 在类上面加装饰器
      @method_decorator(outer,name='post')
      @method_decorator(outer,name='get')
      class LoginView(View):
          def get(self,request):
              print('get方法来啦')
              return render(request,'home.html')

          def post(self,request):
              print('post方法来啦')
              return HttpResponse('ok')
原文地址:https://www.cnblogs.com/weiweivip666/p/13294109.html