Django-- view layer (views)

View function

  1. View function, referred to as view corresponding mapping and routing by urls.py.
  2. Views.py view function defined by default in the file, a request for handling information and Web == == function returns response information
  3. Research view function can master the two objects.

Request object (the HttpRequest)

  1. Premise: According to the previous two days of learning already know the http protocol request message contains the request line, header information, / r / n content body.
  2. The requested content Django http protocol packets encapsulated in the request data HttpRequest object, Django httprequest objects will request the first parameter as the argument to the view function, the http protocol can be extracted by accessing the property of the object.

Common Object Attribute 1 HttpRequest

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

二.HttpRequest.GET
  值为一个类似于字典的QueryDict对象,封装了GET请求的所有参数,可通过HttpRequest.GET.get('键')获取相对应的值
  
三.HttpRequest.POST
   值为一个类似于字典的QueryDict对象,封装了POST请求所包含的表单数据,可通过HttpRequest.POST.get('键')获取相对应的值
   
   针对表单中checkbox类型的input标签、select标签提交的数据,键对应的值为多个,需要用:HttpRequest.POST.getlist("hobbies")获取存有多个值的列表,同理也有HttpRequest.GET.getlist("键")

Case:

urls.py add mapping relationship

from django.urls import re_path
from app01 import views

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

In views.py function to process web requests information and returns response information

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('提交成功')

Under the new HTML page templates directory login.html

在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 object common attributes 2

HttpRequest.body:

   当浏览器基于http协议的POST方法提交数据时,
   数据会被放到请求体中发送给django,django会将接收到的请求体数据存放于HttpRequest.body属性中
   因为该属性的值为Bytes类型,所以通常情况下直接处理Bytes、并从中提取有用数据的操作是复杂而繁琐的,
   django会对它做进一步的处理与封装以便我们更为方便地提取数据

Forms for form, the method used to submit data for the GET and POST

When the data transmission request GET, POST request to the data is

1.表单属性 method=='GET' 提交表单的时候,表单内数据不会存放在请求体中,而是将会表单数据按照k1=v1&k2=v2&k3=v3的格式放在url中,然后发送给django,django会将这些数据封装到request.GET中,这个时候request.body是为空
2.表单属性为'POST',request.body提交表单的时候,表单的数据都会存放在请求体,django封装request.body里面,然后django为了方便提取数据做进一步的处理.

form of a data table form has filed two common encoding format set by the enctype,

编码格式1(默认的编码格式) enctype='application/x-www-form-urlencoded'
编码格式2(使用form表单上传文件时只能这个编码):enctype='multipart/form/-data'
编码格式2数据量要大于编码格式1 如果不需要上传文件,那么就推荐同编码格式1比较精简

Stories from form to upload files

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(requets.body)
        # 从request.POST中获取用户名
        name = request.POST.get('name')
        

New register.html in the templates directory

Create a form, the form necessary to change the encoding format multipart / form-data

<!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>

Common properties HttpRequest object 3

1.HttpRequest.path
    获取url地址的路径部分,只包含路径部分
2.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"   

Case:

url.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 object common attributes part4

一.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') 装饰你的视图以让响应能够正确地缓存。

Response Object

Responses can be any form of content, HTML file content, redirects, error, xml document, a picture. No matter what view contains logic should return a response

Three Musketeers response

from django.shortcuts import HttpResponse,render,redirect

HttpResponse()

With a particular string in brackets as a direct response body, simple and straightforward

render()

render(request,template_name[context])
1.request 用户生成响应的请求对象,固定必须传入的第一个参数
2. template_name:要是用的模板完整的名称,必须传,render就会去templates文件夹下找模板文件,
3 context  可以选的参数, 可以传一个字典用来替换模板文件中的变量 

redirect()

Returns a redirect address, it can be a full url

return redirect('/xxx/')

return redirect('http"//www.baidu.com/')

301 and 302 redirect status difference

301代表旧地址资源被永久移除.搜索引擎在抓取新内容的时候也将就得网址转换成重定向之后的地址

302表示旧地址资源还在(与上面相反)临时从旧到新地址

Summary: From the SEO level considered better than the 302 301

JsonResponse

Look at the code

Returns a json format string in two ways to the distal end

JsonResponse default only supports serialization dictionary if you want to serialize other types (json types that can be supported) you need to safe parameters changed from the default of True False

method one

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

Second way

from django.http import JsonResponse
def my_view(request):
    data = ['egon',kevin]
    return JsonResponse(data,safe=False)

JsonResponse
    返回json格式数据的
    
    为什么要给前端返回json格式字符串
    
    前后端分离  就是基于json格式传输数据
    后端就专门写接口 前端调用你这个接口 就能够拿到一个
    json格式的字符串
    然后前端利用序列化反序列转换成前端对应的数据类型
    
    js常用数据类型
        数值类型
        字符类型
        数组  []
        自定义对象 {}
        undefined与null
        布尔值 true false
        symbol

        前端                          后端
        JSON.stringify 序列化   >>>   json.dumps
        JSON.parse     反序列   >>>   json.loads

        复习
            python后端
                json.dumps
                json.loads

FBV and CBV

django view layer is composed of two forms: FBV and CBV

  1. View FBV function (Function Base View) based
  2. CBV view class-based (Class Base View)

form form to upload files
Notes
1. The submission must be POST
2.enctype parameters must have default urlencoded become formdata

views.py

from django.shortcuts import render
def up(request):
    if request.method == 'POST':
        print(request.POST)

I.e. FBV and CBV CBV source analysis
FBV (Function Based View) based on the view function

problem:

CBV(Class Based View) 基于类的视图
    你在类中写了两个方法 一个叫get一个叫post
    为什么前端get请求来就会触发get方法
    post请求来就会触发post方法  如何实现的???

1.CBC and FBV on the route matching rules are the same, are the route followed by the function of memory address,

2.as_view () click on the go will find that it contains a closure function, the function returns is the view, the view function inside an object to do is to write your own class to produce the assignment,

3.view function returned to the dispatch method, which did get a lowercase string and post screening, if not in the default mode of 8 request, it returns a function of the error,

4, then the address will be reflected getattr function recalling the last acquisition method

    # CBV路由
    url(r'^reg/',views.MyReg.as_view())
    
    @classonlymethod
    def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)  # cls就是我们自己的写的MyReg类
            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)
            # 对象在查找属性或方法的时候 顺序是什么?  先从自己找 再从产生对象的类中找  再去类的父类中找...
            """也就意味着你在看源码的时候 你一定要牢记上面的话"""
        return view
    
    # views.py 
    from django.views import View
    class MyReg(View):
        def get(self,request):
            return render(request,'reg.html')

        def post(self,request):
            return HttpResponse("我是MyReg类中post方法")

"" "CBV most part of the essence." ""

        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)

handler = getattr(自己写的类产生的对象,'小写的请求方法(get\post)','获取不到对应的方法就报错')

handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址

​            else:
​                handler = self.http_method_not_allowed
​            return handler(request, *args, **kwargs)  # 在调用获取到的方法
​    

Case:

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)

test:

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

CBV can be introduced using the idea of ​​object-oriented data a higher degree of encapsulation

Guess you like

Origin www.cnblogs.com/jhpy/p/11729658.html