04 视图层

04 视图层

1. 视图函数

视图函数,简称视图,属于Django的视图层,默认定义在views.py文件中,是用来处理web请求信息以及返回响应信息的函数,所以研究视图函数只需熟练掌握两个对象即可:请求对象(HttpRequest)和响应对象(HttpResponse)

2. 请求对象

当一个页面被请求时,django会创建一个包含本次请求原信息(如http协议请求报文中的请求行、首部信息、内容主体)的HttpRequest对象。

之后,django会找到匹配的视图,将该对象传给视图函数的第一个参数,约定俗称该参数名为request(类似于我们自定义框架的environ参数)。

在视图函数中,通过访问该对象的属性便可以提取http协议的请求数据

2.1 request对象常用属性 1

.HttpRequest.method
  获取请求使用的方法(值为纯大写的字符串格式)。例如:"GET""POST"
   应该通过该属性的值来判断请求方法

   在视图函数中:
   if request.method. == "GET":
       ...
   if request.method == "POST":
       ...
'''
request.mothod  请求方式
request.POST  	POST请求
request.GET		GET请求		
request.FILES	获取前端传的文件格式

request.path	获取路径
request.path_info
request.get_full_path()   能获取完整的url及问号后面的参数
request.body  # 原生的浏览器发过来的二进制数据
'''
print(request.path)  # /app01/ab_file
print(request.path_info)  # /app01/ab_file/
print(request.get_full_path())  # /app01/ab_file/?username=wyz

2.2 request对象常用属性 2

1.1 当浏览器基于http协议的GET方法提交数据时,数据会按照k1=v1&k2&v2的格式放到url中,然后发送给django,django会将这些数据封装到request.GET中,
1.2 当浏览器基于http协议的POST方法提交数据时数据会被放到请求体中发送给django,django会将接收到的请求体数据存放于HttpRequest.body属性中,但该属性的值为Bytes类型(套接字数据传输都是bytes类型),而通常情况下直接处理Bytes,并从中提取有用数据的操作是复杂而繁琐的,好在django会对它做进一步的处理与封装以便我们更为方便地提取数据,具体如何处理呢?
当前端采用POST提交数据时,数据有三种常用编码格式,编码格式不同Django会有不同的处理方式
# 编码格式一 urlencode,是form表单默认编码格式(request.post 获取数据)
# 编码格式二 form-data 上传文件专用格式(request.FILES获取数据)
# 编码格式三 json 提交json格式字符串(request.post)

 1.3 如何设定POST提交数据的编码格式 
    前端往后台POST提交数据,常用技术有form表单和ajax两种
    form表单可以设置的数据编码格式有:编码格式1、编码格式2
    ajax可以设置的数据编码格式有:编码格式1、编码格式2、编码格式3

2.4、HttpRequest对象常用属性3(暂作了解)

"""
  django将请求报文中的请求行、头部信息、内容主体封装成 HttpRequest 类中的属性。
   除了特殊说明的之外,其他均为只读的。
""".HttpRequest.META
   值为包含了HTTP协议的请求头数据的Python字典,字典中的key及期对应值的解释如下
    CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
    CONTENT_TYPE —— 请求的正文的MIME类型。
    HTTP_ACCEPT —— 响应可接收的Content-Type。
    HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
    HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
    HTTP_HOST —— 客服端发送数据的目标主机与端口
    HTTP_REFERER —— Referring 页面。
    HTTP_USER_AGENT —— 客户端使用的软件版本信息
    QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
    REMOTE_ADDR —— 客户端的IP地址。
    REMOTE_HOST —— 客户端的主机名。
    REMOTE_USER —— 服务器认证后的用户。
    REQUEST_METHOD —— 一个字符串,例如"GET""POST"。
    SERVER_NAME —— 服务器的主机名。
    SERVER_PORT —— 服务器的端口(是一个字符串)。
   从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,HTTP协议的请求头数据转换为 META 的键时,
    都会
    1、将所有字母大写
    2、将单词的连接符替换为下划线
    3、加上前缀HTTP_。
    所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

注意:下述常用属性暂且了解即可,待我们讲到专门的知识点时再专门详细讲解
二.HttpRequest.COOKIES
  一个标准的Python 字典,包含所有的cookie。键和值都为字符串。

三.HttpRequest.session
  一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。

11.HttpRequest.user(用户认证组件下使用)

  一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。

2.HttpRequest.is_ajax()

  如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。

  大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。

  如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
   你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。

四.HttpRequest.encoding
  一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
   这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。
   接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
   如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。

五.HttpRequest.scheme
   表示请求方案的字符串(通常为http或https)

六.HttpRequest.user
  一个AUTH_USER_MODEL类型的对象,表示当前登录的用户。

  如果用户当前没有登录,user将设置为django.contrib.auth.models.AnonymousUser的一个实例。
你可以通过is_authenticated()区分它们,例如:

    if request.user.is_authenticated():
        # Do something for logged-in users.
    else:
        # Do something for anonymous users.

    HttpRequest.user只有当Django 启用 AuthenticationMiddleware中间件时才可用。



    匿名用户
    class models.AnonymousUser

    django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:

    id 永远为None。
    username 永远为空字符串。
    get_username() 永远返回空字符串。
    is_staff 和 is_superuser 永远为False。
    is_active 永远为 False。
    groups 和 user_permissions 永远为空。
    is_anonymous() 返回True 而不是False。
    is_authenticated() 返回False 而不是True。
    set_password()、check_password()、save() 和delete() 引发 NotImplementedError。
    New in Django 1.8:
    新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。

3.三板斧

3.1、HttpResponse

传递字符串

from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")

'''
ps:Content-Type用于指定响应体的MIME类型

MIME类型:
mime类型是多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开


MIME 类型有非常多种,一般常见的有:

  text/html:浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。

  text/plain:意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理。

  image/jpeg:JPEG格式的图片

  image/gif:GIF格式的图片

  video/quicktime:Apple 的 QuickTime 电影

  application/vnd.ms-powerpoint:微软的powerpoint文件
'''

3.2、render

def render(request, template_name, context=None, content_type=None, status=None, using=None):
    """
    Return a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, request, using=using)
    return HttpResponse(content, content_type, status)

参数:
    1、request:用于生成响应的请求对象,固定必须传入的第一个参数

    2、template_name:要使用的模板的完整名称,必须传入,render默认会去templates目录下查找模板文件

    3、context:可选参数,可以传入一个字典用来替换模块文件中的变量,默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。

    4、content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'

    5、status:响应的状态码。默认为2006、useing: 用于加载模板的模板引擎的名称。

综上,render的功能可以总结为:根据给定字典渲染模板文件,并返回一个渲染后的HttpResponse对象。

3.3、redirect

返回重定向对象,返回的状态码为302,第一个参数用来指定浏览器重定向的地址,可以是
#1、一个完全标准的URL地址,如'https://www.yahoo.com/search/'
#2、也可以是一个没有域名的绝对路径,如'/search/'
#3、或者是一个没有域名的相对路径,如'search/',与1、2直接跳转到指定的绝对路径不同,相对路径需要先与当前路径进行拼后才能跳转,例如:如果当前路径为http://127.0.0.1:8080/index/,拼接后的路径为http://127.0.0.1:8080/index/search/



# ps:redirect重定向等同于下述操作
def index(request):
    response=HttpResponse()

    response.status_code=302 # 必须设置响应的状态码,才能重定向
    response['Location']='/register/' # 设置响应头

    return response

4. JsonResponse对象

向前端返回一个json格式字符串的两种方式

方式一:

import json

def my_view(request):
    data=['egon','kevin']
    return HttpResponse(json.dumps(data) )

方式二:

from django.http import JsonResponse


# Create your views here.
def ad_json(request):
    user_dic = {'username': 'wyz真帅,雀食蟀'}
    l = [11, 22, 22]

    return JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})

# JsonResponse默认不能转化列表,将safe设置成False即可
    return JsonResponse(l, safe=False)

5. form表单上传文件及后端如何操作

'''
form表单上传文件类型的数据
	1.method必须指定成post
	2.enctype必须换成formdata
	
'''
后端中
def formh(request):
    if request.method == 'POST':
        # print(request.POST)  # 只能获取普通的简直对数据 文件不行
        print(request.FILES)  # <MultiValueDict: {'file': [<InMemoryUploadedFile: 1.png (image/png)>]}>
    return render(request, 'formH.html')

6. FBV与CBV

# 视图函数既可以是函数也可以是类
def index(request):
    return HttpResponse('index')

# CBV
	# CBV路由
    url(r'^login/',views.MyLogin.as_view())
    
'''
FBV和CBV各有千秋
CBV特点
	能够直接根据请求方式的不同直接匹配到对应的方法执行
	
	
	内部到底是怎么实现的?
		CBV内部源码
'''

7. 分析CBV源码代码

小提示:看python源码时,一定要时刻提醒自己面向对象属性方法查找顺序,

先从自己对象找,再去产生对象的类里面找,之后去父类去找

总结:看源码只要看到了self点一个东西,就一定要搞清楚这个self到底是谁

# 突破口在urls.py
 url(r'^login/', views.Mylogin.as_view()),
     # 上述代码再启动django的时候就会立刻执行as_view方法
    # url(r'^login/', views.view)  和 FBV一模一样
    # CBV和FBV在路由匹配本质上是一样的
    函数/方法 加括号执行优先级最高
as_view()
    是被@classmethod修饰的类方法
    @classonlymethod
    def as_view(cls, **initkwargs):
        pass
    
  # 源码 精简版
    def as_view(cls, **initkwargs):
  
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # self = cls(**initkwargs) 相当于Mylogin(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
            return self.dispatch(request, *args, **kwargs)
        return view

    def dispatch(self, request, *args, **kwargs):
        # 获取当前请求方式的小写格式,然后比对当前请求方式是否合法
        # 以get请求为例
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            # 反射getattr方法,self是自己写的类实例的对象,get方法找得到,获得get方法,找不到就会用到第三个参数(报错)
            # handler = 我们自己写的类(Mylogin)里面的get方法
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
            # 自动调用get方法
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值