四、Django的views

Django的视图相关(views)

  1. 请求相关的属性方法(request--HttpRequest对象)

request的方法:

  • request.method:获取请求的方式,'GET'、'POST'

  • request.body:获取post请求提交过来的原始数据,bytes类型,b'username=alex'

  • request.GET:获取GET请求提交的数据
    request.POST:获取POST请求提交的数据
    request.GET.get('year')
    request.POST.get('year')

  • request.META:请求头相关信息,就是一个大字典

  • request.path: 路径 ,/index/
    request.path_info: 路径 ,/index/

  • request.get_full_path():get请求的ip和端口后面的所有,即:路径+数据,/index/?username=dazhuang&password=123

    from django.shortcuts import render,HttpResponse

    def index(request):
    if request.method == 'GET':
    print(request.body) # b''
    print(request.GET) # <QueryDict: {'year': ['2018'], 'month': ['12']}>
    print(request.GET.get('year')) # 2018
    print(request.META) # 请求头相关信息,就是一个大字典
    print(request.path) # /index/ 路径
    print(request.path_info) # /index/ 路径
    print(request.get_full_path()) # /index/?year=2018&month=12
    return render(request,'index.html')
    else:
    print(request.body) # b'year=2018&month=12'
    print(request.POST) # <QueryDict: {'year': ['2018'], 'month': ['12']}>
    print(request.POST.get('year')) # 2018
    return HttpResponse('查询了哈哈~~')

  1. 响应相关的方法
  • HttpResponse --- 回复字符串的时候来使用
  • render --- 回复一个html页面的时候使用
  • redirect -- 重定向
    • 经过操作之后帮助你自动跳转到别的页面。比如一个网站,有些功能需要登录才能访问,所以在用户点击那个功能后,先返回给用户一个登录的页面,在用户登录成功之后就自动跳转到用户点击那个功能的那个页面,不需要用户登陆成功之后再回去点击,提高了用户的体验
    • 在网站更新时,不维护老网站了,重新开发了一个新网站。当有用户访问老网站的时候,就重定向到这个新的网站。
    • 重定向状态码301和302的区别:
      • 301:表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
      • 302:表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。

示例:用户访问网站,让用户输入用户名、密码,判断如果正确,进入到会员页面

  1. urls:
    from django.conf.urls import url
    from app01 import views

    urlpatterns = [
        url(r'^login/', views.login),
    ]
    
  2. login.html:

    登录页面——请登录会员

    <form action="" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="text" name="password">
        <button>提交</button>
    </form>
    
  3. views
    from django.shortcuts import render,HttpResponse

    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'yangzm' and password == '17130':
                return render(request,'member.html')
                
            else:
                return HttpResponse('您不是我们的用户')
    

    这个方法没有用重定向,也完成了相关的功能,但是会发现,此时的域名还是 login/,这样是不合适的,不能还是原来的地址,需要跳转到一个新的网页地址

    改进的views:
    urls.py文件里面添加一个member的路径
    urlpatterns = [
    url(r'^login/', views.login),
    url(r'^member/', views.member),
    ]

    from django.shortcuts import render,HttpResponse
    
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'yangzm' and password == '17130':
                # return render(request,'member.html')
                return redirect('/member/')
            else:
                return HttpResponse('您不是我们的用户')
    
    def member(request):
        return render(request, 'member.html')
    

    这个时候,登录成功就跳转到一个新的网址了

  4. FBV和CBV

FBV(function base views) 就是在视图里使用函数处理请求。

CBV(class base views) 就是在视图里使用类处理请求。

比如处理一个GET方法的views,用函数写:

FBV

from django.http import HttpResponse
  
def my_view(request):
     if request.method == 'GET':
            return HttpResponse('OK')

然后用类的方法来写:

CBV

views.py:
    from django.http import HttpResponse
    from django.views import View   # 需要导入View

    class MyView(View):   
        # 通过请求方法找到自己写的视图类里面对应的方法
        def get(self, request):    # 必须写的get,要和请求'GET'对应
            return HttpResponse('OK')
    
urls.py
	url(r'^myview/', views.MyView.as_view()),

CBV是如何通过不同的请求方法找到对应的试图类中的方法?

  • 首先urls.py中,views.MyView.as_view() ,是MyView调用了as_view()这个方法,而MyView是我们自己创建的类,是没有as_view()这个方法的,所以class MyView(View),就是继承的View里面的as_view()方法

  • 点开View的源码:关键点——反射
    class View(object):
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    ......
    def as_view(cls, **initkwargs):
    ......
    def view(request, *args, kwargs):
    self = cls(
    initkwargs)
    ......
    return self.dispatch(request, *args, **kwargs) # 主要方法

            return view
            
        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)
    

    as_view()静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()方法,dispatch()方法会根据request的method的不同调用相应的方法来处理request(如get(),post()等)

CBV的dispatch方法

# 通过重写dispatch方法,可以在执行请求(get,post等)之前之后做一些拓展

class MyView(View):

    def dispatch(self, request, *args, **kwargs):
        print('请求之前的内容~~~~~')
        ret = super().dispatch(request,*args, **kwargs)
        print('请求之完事啦')
        return ret

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

    def post(self,request):
        username = request.POST.get('uname')
        password = request.POST.get('pwd')
        print(username,password)
        return HttpResponse('登录成功!')
    
    
# 结果:
	# 在访问页面时,get请求执行:
		请求之前的内容~~~~~
		get方法执行了
		请求之完事啦
    # 在input框输入用户名密码,提交,发送的post请求执行:
    	请求之前的内容~~~~~
		yangzm 123
		请求之完事啦	
  1. 加装饰器

FBV加装饰器

# 就是正常写个装饰器,然后用语法糖就行

def warpper(f):
    def inner(*args,**kwargs):
        print('请求之前')
        ret = f(*args,**kwargs)
        print('请求之后')
        return ret
    return inner

@warpper
def my_view(request):
    if request.method == 'GET':
        return HttpResponse('OK')

CBV加装饰器

# 先导入 method_decorator 
# 有三种方法:
	# 方式一: 
    	@method_decorator(warpper) # 给某个请求添加装饰器
        def get(self,request):
            pass
	# 方式二: 
    	@method_decorator(warpper) # 给所有方法加装饰器
        def dispatch(self,request, *args, **kwargs):
            pass
	# 方式三:
    	@method_decorator(warpper,name='get') # 给某个方法加装饰器
		class MyView(View):
            pass
        
        
from django.views import View
from django.utils.decorators import method_decorator # Django提供的装饰器

def warpper(f):
    def inner(*args,**kwargs):
        print('请求之前')
        ret = f(*args,**kwargs)
        print('请求之后')
        return ret
    return inner

@method_decorator(warpper,name='get') # 方式三:只给get请求加
class MyView(View):

    @method_decorator(warpper) # 方式二:给所有请求加
    def dispatch(self, request, *args, **kwargs):
        print('请求之前的内容~~~~~')
        ret = super().dispatch(request,*args, **kwargs)
        print('请求之完事啦')
        return ret
	
    @method_decorator(warpper) # 方式一:只给get请求加
    def get(self,request):
        print('get方法执行了')
        return render(request,'login.html')

    def post(self,request):
        username = request.POST.get('uname')
        password = request.POST.get('pwd')
        print(username,password)
        return HttpResponse('登录成功!')

5.简单总结

请求相关request

request.method  请求方法
request.body    post请求原始数据
request.POST
request.GET
request.path  获取路径
request.path_info  
request.get_full_path()  获取路径及参数

request.META 请求头相关信息

响应相关

HttpResponse  
render  
redirect

FBV和CBV

def index(request):
	return render(request,'xx.html')
	

from django.views import View	
class Index(View):
	def dispatch(self,request,*args,**kwargs):
		请求前干点儿事
		ret = super().dispatch(request,*args,**kwargs)
		请求后干点儿事儿
		return ret
	def get(self,request):
		...
    def post(self,request):
		...

装饰器

def wrapper(f):
	def inner(*args,**kwargs):
		前戏
		ret = f(*args,**kwargs)
		收工
		return ret
	return inner

@wrapper
def index(request):
	return render(request,'xx.html')

from django.utils.decorators import method_decorator

@method_decorator(wrapper,name='get')
class Index(View):
    
	@method_decorator(wrapper)
	def dispatch(self,request,*args,**kwargs):
		请求前干点儿事
		ret = super().dispatch(request,*args,**kwargs)
		请求后干点儿事儿
		return ret
		
	@method_decorator(wrapper)
	def get(self,request):
		...
    def post(self,request):
    	...
原文地址:https://www.cnblogs.com/yangzm/p/11209944.html