Django之视图层

Django之视图层

视图函数

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

undefined

请求对象(HttpRequest)

djangohttp协议请求报文中的请求行、首部信息、内容主体封装到了HttpRequest对象中(相似于咱们自定义框架的environ参数)。 django会将HttpRequest对象当作参数传给视图函数的第一个参数request,在视图函数中,经过访问该对象的属性即可以提取http协议的请求数据html

HttpRequest对象经常使用属性part1

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

  2. HttpRequest.GET
      值为一个相似于字典的QueryDict对象,封装了GET请求的全部参数,可经过HttpRequest.GET.get(‘键’)获取相对应的值python

  3. HttpRequest.POST
    值为一个相似于字典的QueryDict对象,封装了POST请求所包含的表单数据,可经过HttpRequest.POST.get(‘键’)获取相对应的值web

    针对表单中checkbox类型的input标签、select标签提交的数据,键对应的值为多个,须要用:HttpRequest.POST.getlist("hobbies")获取存有多个值的列表,同理也有HttpRequest.GET.getlist(“键”)ajax

案例:数据库

urls.pydjango

from django.urls import re_path
from app01 import views

urlpatterns = [
    re_path(r'^login/$',views.login),
]

Views.pyjson

from django.shortcuts import render,HttpResponse

def login(request):
    if request.method == 'GET':
        # 当请求url为:http://127.0.0.1:8001/login/?a=1&b=2&c=3&c=4&c=5
        # 请求方法是GET,?后的请求参数都存放于request.GET中
        print(request.GET)
        # 输出<QueryDict: {'a': ['1'], 'b': ['2'], 'c': ['3', '4', '5']}>

        # 获取?后参数的方式为
        a=request.GET.get('a') # 1
        b=request.GET.get('b') # 2
        c=request.GET.getlist('c') # ['3', '4', '5']

        return render(request,'login.html')
    elif request.method == 'POST':
        # 在输入框内输入用户名egon、年龄18,选择爱好,点击提交
        # 请求方法为POST,表单内的数据都会存放于request.POST中
        print(request.POST) 
        # 输出<QueryDict: {..., 'name': ['egon'], 'age': ['18'], 'hobbies': ['music', 'read']}>

        # 获取表单中数据的方式为
        name=request.POST.get('name') # egon
        age=request.POST.get('age') # 18
        hobbies=request.POST.getlist('hobbies') # ['music', 'read']

        return HttpResponse('提交成功')

templates目录下新建login.html浏览器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆页面</title>
</head>
<body>

<!--
method="post"表明在提交表单时会以POST方法提交表单数据
action="/login/" 表明表单数据的提交地址为http://127.0.0.1:8001/login/,能够简写为action="/login/",或者action=""
-->
<form action="http://127.0.0.1:8001/login/" method="post">
    {% csrf_token %} <!--强调:必须加上这一行,后续咱们会详细介绍-->
    <p>用户名:<input type="text" name="name"></p>
    <p>年龄:<input type="text" name="age"></p>
    <p>
        爱好:
        <input type="checkbox" name="hobbies" value="music">音乐
        <input type="checkbox" name="hobbies" value="read">阅读
        <input type="checkbox" name="hobbies" value="dancing">跳舞
    </p>
    <p><input type="submit" value="提交"></p>

</form>
</body>
</html>

HttpRequest对象经常使用属性part2

一.HttpRequest.body
   当浏览器基于http协议的POST方法提交数据时,数据会被放到请求体中发送给django,django会将接收到的请求体数据存放于HttpRequest.body属性中,由于该属性的值为Bytes类型,因此一般状况下直接处理Bytes、并从中提取有用数据的操做是复杂而繁琐的,好在django会对它作进一步的处理与封装以便咱们更为方便地提取数据,好比
   对于form表单来讲,提交数据的经常使用方法为GET与POST
   1:若是表单属性method='GET',那么在提交表单时,表单内数据不会存放于请求体中,而是会将表单数据按照k1=v1&k2=v2&k3=v3的格式放到url中,而后发送给django,django会将这些数据封装到request.GET中,注意此时的request.body为空、无用
   2:若是表单属性method='POST',那么在提交表单时,表单内的全部数据都会存放于请求体中,在发送给django后会封装到request.body里,此时django为了方便咱们提取数据,会request.body的数据进行进一步的处理,具体如何处理呢,须要从form表单提交数据的编码格式提及:
    form表单对提交的表单数据有两种经常使用的编码格式,能够经过属性enctype进行设置,以下
    编码格式1(默认的编码格式):enctype="application/x-www-form-urlencoded" 
    编码格式2(使用form表单上传文件时只能用该编码):enctype="multipart/form-data" 
    若是form表单提交数据是按照编码格式1,那么request.body中数据的格式相似于GET方法的数据格式,如k1=v1&k2=v2,此时django会将request.body中的数据提取出来封装到request.POST中方便咱们提取
    若是form表单提交数据是按照编码格式2,那么request.body中数据的格式为b'------WebKitFormBoundaryKtcwuksQltpNprep\r\nContent-Disposition: form-data;......',,此时django会将request.body中的数据提取出来封装到request.POST中,将上传的文件数据专门提取出来封装到request.FILES属性中
    强调:毫无疑问,编码格式2的数据量要大于编码格式1,若是无需上传文件,仍是推荐使用更为精简的编码格式1
    
    咱们除了能够采用form表单向django提交数据外,还能够采用ajax技术,ajax能够提交的数据格式有:一、编码格式1 二、编码格式2 三、json,当ajax采用POST方法提交前两种格式的数据时,django的处理方案同上,可是当ajax采用POST方法提交json格式的数据时,django会将接收到的数据存放于HttpRequest.body,此时须要咱们本身对HttpRequest.body属性值作反序列化操做,
具体的,咱们在讲解ajax时再作具体介绍
    
二.HttpRequest.FILES
   若是使用form表单POST上传文件的话,文件数据将包含在HttpRequest.FILES属性中。

  该属性值为一个相似于字典的对象,能够包含多组key:value(对应多个上传的文件),其中每一个key为<input type="file" name="" /> 中name属性的值,而value则为对应的文件数据
  强调:HttpRequest.FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的状况下才会包含数据。不然,FILES 将为一个空的相似于字典的对象。

undefined

案例:form表单上传文件

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^register/$',views.register),
]

views.py

from django.shortcuts import render,HttpResponse

def register(request):
    if request.method == 'GET':
        return render(request,'register.html')
    elif request.method == 'POST':
        print(request.body)

        # 从request.POST中获取用户名
        name=request.POST.get('name') 
        # 从request.FILES获取文件对象
        file_obj=request.FILES.get('header_img') 
        
        # 上传的文件存放于templates文件夹下
        with open('templates/header.png','wb') as f: 
            for line in file_obj:
                f.write(line)

        return HttpResponse('注册成功')

templates目录下新建register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>

<form action="" method="POST" enctype="multipart/form-data" >
    {% csrf_token %}
    <p>
        用户名:<input type="text" name="name">
    </p>
    <p>
        头像:<input type="file" name="header_img">
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>
</body>
</html>

HttpRequest对象经常使用属性part3

一.HttpRequest.path
  获取url地址的路径部分,只包含路径部分

二.HttpRequest.get_full_path()
  获取url地址的完整path,既包含路径又包含参数部分

若是请求地址是http://127.0.0.1:8001/order/?name=egon&age=10#_label3,
HttpRequest.path的值为"/order/"
HttpRequest.get_full_path()的值为"/order/?name=egon&age=10"

案例:

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^order',views.order),
]

views.py

from django.shortcuts import render,HttpResponse

# 针对请求的url地址:http://127.0.0.1:8001/order/?name=egon&age=10#_label3
# 从域名后的最后一个“/”开始到“?”为止是路径部分,即/order/
# 从“?”开始到“#”为止之间的部分为参数部分,即name=egon&age=10
def order(request):
    print(request.path) # 结果为“/order/”
    print(request.get_full_path()) # 结果为"/order/?name=egon&age=10"

    return HttpResponse('order page')

HttpRequest对象经常使用属性part4

undefined

一.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 的键时,
    都会
    一、将全部字母大写
    二、将单词的链接符替换为下划线
    三、加上前缀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') 装饰你的视图以让响应可以正确地缓存。

响应对象(HttpResponse)

响应能够是任何形式的内容,好比一个HTML文件的内容,一个重定向,一个404错误,一个XML文档,或者一张图片等。总之,不管视图自己包含什么逻辑,都要返回响应,具体的说,响应对象主要有三种形式:HttpResponse,render,redirect

from django.shortcuts import HttpResponse,render,redirect

HttpResponse()

括号内直接跟一个具体的字符串做为响应体,比较直接很简单,因此这里主要介绍后面两种形式。

render()

render(request, template_name[, context])
参数:
    一、request:用于生成响应的请求对象,固定必须传入的第一个参数

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

    三、context:可选参数,能够传入一个字典用来替换模块文件中的变量

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

redirect()

# 返回重定向信息
def my_view(request):
    ...
    return redirect('/some/url/')

# 重定向的地址也能够是一个完整的URL:
def my_view(request):
    ...
    return redirect('http://www.baidu.com/') 

undefined

重定向转态码301与302的区别(了解)

1、301和302的异同。
   一、相同之处:
   301和302状态码都表示重定向,具体点说就是浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址(浏览器会从响应头Location中获取新地址),用户看到的效果都是输入地址A后瞬间跳转到了另外一个地址B
   
   二、不一样之处:
  301表示旧地址A的资源已经被永久地移除了,即这个资源不可访问了。搜索引擎在抓取新内容的同时也将旧的网址转换为重定向以后的地址;
  302表示旧地址A的资源还在,即这个资源仍然能够访问,这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容、而且会保存旧的网址。 从SEO层面考虑,302要好于301

2、重定向缘由:
   一、网站调整(如改变网页目录结构);
   二、网页被移到一个新地址;
   三、网页扩展名改变(如应用须要把.php改为.Html或.shtml)。
      这种状况下,若是不作重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户获得一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也须要经过重定向让访问这些域名的用户自动跳转到主站点等。

JsonResponse

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

方式一:

import json

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

方式二:

from django.http import JsonResponse

def my_view(request):
    data=['egon','kevin']
    return JsonResponse(data,safe=False)
    #默认safe=True表明只能序列化字典对象,safe=False表明能够序列化字典之外的对象

FBVCBV

django的视图层由两种形式构成:FBVCBV

  1. FBV基于函数的视图(Function base view),咱们以前一直介绍的都是FBV
  2. CBV基于类的视图(Class base view)

案例:

urls.py

from django.urls import path,register_converter,re_path
from app01 import views

urlpatterns = [
    re_path(r'^login/',views.LoginView.as_view()), # 必须调用类下的方法as_view
]

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.views import View

class LoginView(View):
    def dispatch(self, request, *args, **kwargs): # 可在该方法内作一些预处理操做
        # 当请求url为:http://127.0.0.1:8008/login/会先触发dispatch的执行
        # 若是http协议的请求方法为GET,则调用下述get方法
        # 若是http协议的请求方法为POST,则调用下述post方法
        obj=super().dispatch(request, *args, **kwargs) # 必须继承父类的dispatch功能
        return obj # 必须返回obj

    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        name=request.POST.get('name')
        pwd=request.POST.get('pwd')
        if name  == 'egon' and pwd == '123':
            res='登陆成功'
        else:
            res='用户名或密码错误'
        return HttpResponse(res)

测试:

python manage.py runserver 8001 
# 验证GET请求:在浏览器输入:http://127.0.0.1:8001/login/
# 验证POST请求:在表单内输入数据而后提交

采用CBV能够引入面向对象的思想对数据进行更高程度的封装,此处简单了解便可,咱们将在后续的项目中详细介绍它的应用于强大之处

undefined

相关文章
相关标签/搜索