Django视图层

视图层


视图响应的过程:

当⽤户从浏览器发起⼀次请求时,⾸先django获取⽤户的请求,然后通过路由 (urls)将请求分配到指定的视图函数。视图函数负责进⾏相应的业务处理,处 理完毕后把结果(可能是json、html等)浏览器

1、三板斧

"""
HttpResponse
	返回字符串类型
render
	返回html页面,并且返回给浏览器之前还可以给html文件传值
redirect
	重定向
"""

# 视图函数必须要返回一个HttpResponse对象,研究三者的源码即可得出结论


# render简单内部原理
def inder(request):
    from django.template import Template,Context
    res=Template('<h1>{{ user }}</h1>')
    con=Context({'user':{'username':'zhao','password':123}})
    ret=res.render(con)
    print(ret)
    return HttpResponse(ret)

2、JsonResponse对象

JsonResponseHttpResponse的⼦类,⽤于向客户端返回json数据。⼀般⽤于 ajax请求。它的content-type缺省值为:application/json

"""
json格式数据有什么用?:
	前后端数据交互的时候需要使用json作为过渡,实现跨语言传输数据

前端系列化                      python系列化
	JSON.stringify()			json.dumps()
	JSON.parse()				json.loads()
"""
Django后端给前端返回json格式的数据
	1. 手动利用json模块
    2.利用JsonResponse
  • 方式一: json模块
#方式一:json模块
def ab_json(request):
    user_dic = {'username': '我是谁', 'password': 123, 'hobby': 'JayChou'}

    # 先转成json格式字符串
    # json_str=json.dumps(user_dic,ensure_ascii=False)
    # #将该字符串返回
    # return HttpResponse(json_str)
  • 方式二 :JsonResponse对象
 #方式二 :JsonResponse对象
from django.http import JsonResponse
def ab_json(request):
    user_dic = {'username': '我是谁', 'password': 123, 'hobby': 'JayChou'}
    l=[111,222,33,444]
    # return JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})
    return JsonResponse(l,safe=False)

默认只能序列化字典,序列化其他需要加safe参数

3、form表单上传文件及后端如何操作

"""
from 表单上传文件类型的数据
	1. method必须指定post
	2.enctype必须换成form-data
"""

<form action="" method="post" enctype="multipart/form-data">
    <p>username:<input type="text" name="username"></p>
    <p>file:<input type="file" name="myfile"></p>
    <input type="submit">

</form>


def ab_file(request):
    if request.method == 'POST':
        print(request.POST)  # 只能获取普通的键值对数据
        print(request.FILES)  # 获取文件数据
        file_obj = request.FILES.get('myfile')
        print(file_obj.name)
        with open(file_obj.name, 'wb') as f:
            for line in file_obj:  # chunks方法加与不加都是一样的效果
                f.write(line)
    return render(request, 'form.html')

4、request对象

HttpRequest是从web服务器传递过来的请求对象,经过Django框架封装产⽣的, 封装了原始的Http请求

  • 服务器接收到http请求后,django框架会⾃动根据服务器传递的环境变量创建 HttpRequest对象
  • 视图的第⼀个参数必须是HttpRequest类型的对象
  • 在django.http模块中定义了HttpRequest对象的API
  • 使⽤HttpRequest对象的不同属性值,可以获取请求中多种信息
属性 说明
contenttype 请求的mime类型
GET ⼀个类似于字典的QueryDict对象,包含get请求⽅式的所有参 数,也就是“?”后⾯的内容
POST ⼀个类似于字典的QueryDict对象,包含post请求⽅式的所有参 数
COOKIES ⼀个标准的Python字典,包含所有的cookie,键和值都为字符串
SESSION ⼀个类似于字典的对象,表示当前的会话,只有当Django启⽤会 话的⽀持时才可⽤
PATH ⼀个字符串,表示请求的⻚⾯的完整路径,不包含域名
method ⼀个字符串,表示请求使⽤的HTTP⽅法,常⽤值包括:GET、 POST,
FILES ⼀个类似于字典的QueryDict对象,包含所有的上传⽂件
META 请求的请求头的源信息(请求头中的键值对)
encoding 字符编码
scheme 协议

META中常用的键:

说明
HTTP_REFERER 来源⻚⾯
REMOTE_ADDR 客户端ip
REMOTE_HOST 客户端主机

下⾯是常⽤的⽅法:

方法名 说明
get_host() 获取主机名+端⼝
get_full_path() 获取请求路径+查询字符串
is_ajax() 如果是ajax请求返回True
build_absolute_uri() 完整的url
"""
request.method
request.GET
request.POST
request.FILES
request.is_ajax() 判断当前请求是否是ajax请求,返回布尔值
r
request.path		#只能获取路由
request.path_info   #只能获取路由
request.get_full_path() #能够获取路由以及问号后面的参数
request.body   #原生的浏览器发过来的二进制数据

"""
print(request.path)#/app01/ab_file/
print(request.path_info)#/app01/ab_file/
print(request.get_full_path())#/app01/ab_file/?username=lisi
request.method #返回请求方式。并且是全大写的字符串形式
request.POST #获取用户post请求提交 的普通数据(键值对),不包含文件
	request.POST.get()  #只获取列表最后一个元素
    request.POST.getlist() #直接将列表所有元素取出
    
request.GET   # 获取url问好后面携带的参数
	request.GET.get()  #只获取列表最后一个元素
    request.GET.getlist()  #直接将列表所有元素取出
    
"""
get请求携带的数据是有大小数据的,大概好像只有4k左右
post请求则没有限制
""" 
# 子路由urls.py

 # path,如果有多个参数,path类型必须在最后一个
path('access/<path:path>/', views.access, name='access'),



#views.py

def access(request, path):
    # path 可以包含任何字符,包括 /

    # 获取请求方法
    print(request.method)
    # 获取请求路径
    print(request.path)
    # 其他请求属性
    print(request.META)
    # 客户端地址
    print(request.META.get('REMOTE_ADDR'))
    # 来源页面
    print(request.META.get('HTTP_REFERER'))

    # 常用方法
    print(request.get_host())  # 127.0.0.1:8000
    print(request.get_full_path())
    print(request.build_absolute_uri())

    # 获取请求参数的字典  QueryDict转成dict
    print(request.GET.dict())  # {'name': '12'}
    return HttpResponse(path)

在这里插入图片描述

def login(request):
    """
    get请求和post请求应该有不同的处理机制
    :param request:
    :return:
    """
    # print(request.method)#返回请求方式。并且是全大写的字符串形式
    # print(type(request.method))

    # if request.method == 'GET':
    #     return render(request, 'login.html')
    # elif request.method == 'POST':
    #     return HttpResponse('收到 !!!')

    if request.method == 'POST':
        return HttpResponse('收到')
    return render(request, 'login.html')


在前期使用django提交post请求时,需要去配置文件中注释掉一行代码

MIDDLEWARE = [
   'django.middleware.security.SecurityMiddleware',
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.common.CommonMiddleware',
   # 'django.middleware.csrf.CsrfViewMiddleware',
   'django.contrib.auth.middleware.AuthenticationMiddleware',
   'django.contrib.messages.middleware.MessageMiddleware',
   'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

5、响应对象

每⼀个视图函数必须返回⼀个响应对象,HttResponse对象由程序员创建并返回。

属性 说明
content 字节字符串
charset 字符编码
status_code http状态码
content_type 指定输出的MIME类型
# urls.py
	path('response/', views.handle_response, name='response'),
    
    
 # views.py   
    def handle_response(request):
    res = HttpResponse('响应对象')
    res.content = b'good bye'
 	res.charset = "utf-8"
    res.content_type = 'text/html'
    res.status_code = 400
    return None

image-20221107224043800

6、FBV与CBV

#视图函数既可以是函数也可以是类

#FBV
	#FBV路由
    path('index/',views.index),
    #views.py
    def index(request):
        return HttpResponse('index')

#CBV
    #CBV路由  
    path('login/',views.MyLogin.as_view())
    
    #views.py
    class MyLogin(View):
        #只要是有处理业务逻辑的视图函数,形参里面都应该有request
        def get(self, request):
            return render(request,'form.html')

        def post(self, request):
            return HttpResponse('post方法')

    """
    CBV特点:能够根据请求方式的不同直接匹配到对应的方法执行
    """

7、 CBV添加装饰器

  • 装饰器
# 校验用户是否登录的装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):
        target_url = request.get_full_path()
        if request.COOKIES.get('username'):
            res = func(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/?next=%s' % target_url)

    return inner
  • 添加装饰器 方式一
# views.py
from django.views import View
from django.utils.decorators import method_decorator

class MyLogin(View):
    @method_decorator(login_auth)#方式一
    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')

    
# urls.py
    path('mylogin/',views.MyLogin.as_view())  
  • 添加装饰器 方式二
# views.py
from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(login_auth, name='get')  # 方式二,可以添加多个,针对不同的方法加不同的装饰器
@method_decorator(login_auth, name='post')
class MyLogin(View):
    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')
    
    
# urls.py
    path('mylogin/',views.MyLogin.as_view())
  • 添加装饰器 方式三
# views.py
from django.views import View
from django.utils.decorators import method_decorator


class MyLogin(View):
    @method_decorator(login_auth)  # 方式三,会直接作用于当前类里的所有方法
    def dispatch(self, request, *args, **kwargs): # 
        pass

    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')
    
    
# urls.py
    path('mylogin/',views.MyLogin.as_view())   
posted @ 2022-12-12 15:48  ExpiredSaury  阅读(30)  评论(0编辑  收藏  举报