【Python百日进阶-WEB开发】Day166 - Django视图 View(一)

一、视图介绍和项目准备

在这里插入图片描述

二、URLconf

浏览者通过在浏览器的地址栏输入网址请求网站
对于Django开发的网站,有哪一个视图进行处理请求,是由url匹配找到的,配置流程如下:

2.1 settings.py中

指定url配置:ROOT_URLCONF= ‘项目.urls’
在这里插入图片描述

2.2 项目urls.py

匹配成功后,包含到应用的urls.py:path(‘’,include(‘应用.urls’))
在这里插入图片描述

2.3 应用 urls.py

path(‘’,views.函数名)
在这里插入图片描述

2.4 提示

  • 如果使用正则匹配,推荐r’',不转义
  • 不能在开始加反斜杠(path(‘/path’)),推荐在结束加反斜杠(path(‘path/’))
  • 请求的url被看做是一个普通的python字符串,进行匹配时不包括域名、get和post参数,如请求地址:http://127.0.0.1:8000/18/?a=10,去掉域名和参数部分后,只剩下 18/ 进行正则匹配

三、路由命名与reverse反解析

3.1 路由命名

在这里插入图片描述

from django.urls import path
from book.views import index

urlpatterns = [
    # name就是url的名字,可以通过name找到这个路由
    path('index/', index, name='home'),
]

3.2 reverse反解析,根据名字动态找路由

在这里插入图片描述

from django.http import HttpResponse
from django.shortcuts import render, redirect, reverse
from book.models import BookInfo, PeopleInfo
# Create your views here.
def index(request):
    """
    登录成功、注册成功等都需要跳转到首页
    1、不使用路由名字时的跳转页面
    return redirect('/index/')
    2、使用路由名字时的跳转页面,路由是动态获取
    path = reverse('index')
    return redirect(path)
    """

3.3 namespace 应用命名空间

3.3.1 项目urls中定义namespace

在这里插入图片描述

from django.contrib import admin
from django.urls import path, include
from book.views import index

urlpatterns = [
    path('admin/', admin.site.urls),
    # 在include中添加第二参数 namespace,这样原来路由的name就变成了 namespace:name, 如 book:home
    # namespace习惯上使用子应用的名字,容易识别还不会重名
    path('', include('book.urls', namespace='book')),
]

3.3.2 book应用urls中定义app_name

在这里插入图片描述

from django.urls import path
from book.views import index

app_name = 'book'

urlpatterns = [
    # name就是url的名字,可以通过name找到这个路由
    path('index/', index, name='home'),
]

3.3.3 应用Views中使用namespace:name反解析

在这里插入图片描述

from django.shortcuts import render, redirect, reverse
from book.models import BookInfo, PeopleInfo
# Create your views here.
def index(request):
    """
    登录成功、注册成功等都需要跳转到首页
    1、不使用路由名字时的跳转页面
        return redirect('/index/')
    2、使用路由名字时的跳转页面,路由是动态获取
        path = reverse('home')
        return redirect(path)
    3、如果设置了namespace就需要通过namespace:name来获取路由
        path = reverse('book:home')
        return redirect(path)
    """

四、使用PostMan对请求进行测试

PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件,可以直接去对我们写出来的路由和视图函数进行调试,是后端程序员必须会用的一个工具。

4.1 安装方式

4.1.1 Chrome商店直接搜索PostMan扩展程序进行安装

4.1.2 官网下载桌面版https://www.postman.com/downloads/

在这里插入图片描述
安装
在这里插入图片描述
注册免费账号,
在这里插入图片描述
在这里插入图片描述
保存账号密码,省得每次都得输入
在这里插入图片描述

4.1.3 将已下载好的PostMan插件文件夹拖入Chrome浏览器

4.2 使用方法

在这里插入图片描述

在这里插入图片描述

五、HttpRequest对象

利用HTTP协议向服务器传参有四种途径:

  • 提取URL的特定部分如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取;
  • 查询字符串( query string),形如key1=alue&key=value2;
  • 请求体(body)中发送的数据,比如表单数据、json、xml等
  • 在http报文的头(header)中

5.1 URL路径参数

  • 如果想从URL中获取值,需要在正则表达式中使用分组
  • 获取值分为两种方式
    – 位置参数:参数的位置不能错
    –关键字参数:参数的位置可以变,跟关键字保持一致即可
  • 注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式
  • 分别使用以上两种获取URL值的方式提取出18 188

5.1.1 位置参数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
正则分组匹配所有整数数字 (\d+)
在这里插入图片描述

from django.urls import path
from book.views import index, detail
from django.conf.urls import url

app_name = 'book'

urlpatterns = [
    # name就是url的名字,可以通过name找到这个路由
    path('index/', index, name='home'),
    # http://127.0.0.1:8000/category_id/book_id
    # 根据位置来获取url中传递的参数
    url(r'^(\d+)/(\d+)/$', detail),
]

5.1.2 关键字参数

利用正则别名(?P\d+)传递关键字,推荐使用,不用考虑位置问题,只要关键字对应就行。
在这里插入图片描述
在这里插入图片描述
实际项目路由都是关键字参数
在这里插入图片描述
在这里插入图片描述

from django.urls import path
from book.views import index, detail1, detail2
from django.conf.urls import url

app_name = 'book'

urlpatterns = [
    # name就是url的名字,可以通过name找到这个路由
    path('index/', index, name='home'),
    # http://127.0.0.1:8000/category_id/book_id
    # 根据位置来获取url中传递的参数
    url(r'^(\d+)/(\d+)/$', detail1),
    # 关键字传递参数,推荐使用
    url(r'^(?P<category_id>\d+)/(?P<book_id>\d+)/$', detail2),
]

# 关键字传递参数,函数接收关键字
def detail2(request, categeory_id, book_id):
    print(categeory_id, book_id)
    return HttpResponse('detail')

5.2 查询字符串

获取请求路径中的查询字符串参数(形如?1=v1&k2=v2),可以通过 requestget属性获取,返回QueryDict对象。
注意:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过 request GET获取请求中的查询字符串数据。
PostMan模拟 在这里插入图片描述

5.2.1查询关键字通过 request.GET 参数接收

在这里插入图片描述

5.2.2Django中的QueryDict对象与普通python字典的区别

HttpRequest对象的属性GET、POST都是QueryDict类型的对象
与python字典不同, QueryDict类型的对象用来处理同一个键带有多个值的情况

  • 方法get:根据键获取值,get(‘key’, 默认值)
    如果一个键同时拥有多个值将获取最后一个值
    如果键不存在则返回None值,可以设置默认值进行后续处理
  • 方法 getlist():根据键获取值,值以列表返回可以获取指定键的所有值,getlist(键,默认值)
    如果键不存在则返回空列表,可以设置默认值进行后续处理

在这里插入图片描述
在这里插入图片描述

# 查询字符串
def detail3(request, categeory_id, book_id):
    """
    查询字符串,以百度查询python为例
    https://www.baidu.com/s?wd=python&rsv_spt=1&rsv_iqid=0x8662fdc7003bb4a1&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=49055317_10_hao_pg&rsv_enter=1&rsv_dl=ib&rsv_sug3=17&rsv_sug1=16&rsv_sug7=100
    上面的url以问号作为分隔,前面是路由,https://www.baidu.com/s
    问号后面是get传递的参数,称之为查询字符串,它的形式是,?key=value&key=value&key=value...
    成熟系统中,用户在登录输入用户名和密码的时候,理论上,用户名和密码都应该以POST方式进行传递
    现在,为了便于学习,采用get方式传递用户名和密码
    get传递的用户名和密码在 request.GET 中
    """
    # 前端:http://127.0.0.1:8000/2/200?user_name=zhangsan&password=123
    # query_params = request.GET
    # print(query_params)             # <QueryDict: {'user_name': ['zhangsan'], 'password': ['123']}>
    # print(type(query_params))       # <class 'django.http.request.QueryDict'>
    # # 后台获取用户名密码
    # user_name = query_params['user_name']
    # print(user_name)                  # zhangsan
    # password = query_params.get('password')
    # print(password)                   # 123
    """
    QueryDict 与普通python字典的区别
        1、QueryDict可以获取url中的一键多值,以 key:[value1, ..., value2] 的形式存储
        2、QueryDict获取的一键多值,以普通字典key的方式提取,只能提取到最后的一个值(value2),不能提取到值列表[value1, ..., value2]
        3、想获取QueryDict的一键多值,需要用QueryDict的getlist方法,形如:QueryDict.getlist('user_name')
    """
    # 前端:http://127.0.0.1:8000/2/200?user_name=zhangsan&password=123&user_name=lisi
    query_params = request.GET
    print(query_params)             # <QueryDict: {'user_name': ['zhangsan', 'lisi'], 'password': ['123']}>
    print(type(query_params))       # <class 'django.http.request.QueryDict'>
    # 后台获取用户名密码
    user_name = query_params['user_name']       # 字典key方法,只能获取一键多值的最后一个
    print(user_name)                # lisi
    users = query_params.getlist('user_name')   # QueryDict.getlist方法,可以获取一键多值的值列表
    print(users)                    # ['zhangsan', 'lisi']
    password = query_params.get('password')     # QueryDict.get方法,同字典key方法
    print(password)                 # 123

    return HttpResponse('detail-3')

5.3 请求体

请求体数据格式不固定,可以是表单类型字符串,可以是JSON字符串,可以是ML字符串应区别对待,
可以发送请求体数据的请求方式有 POST、PUT、PATCH、DELETE。
Django默认开后了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制,方法为在 settings py文件中注释掉CSRF中间件。
注意:①网址url以斜线结束。②注释掉settings中的CRSF安全设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.3.1 POST表单数据

在这里插入图片描述
在这里插入图片描述

# POST表单数据,
def detail4(request, categeory_id, book_id):
    print(categeory_id, book_id)
    """
    1、使用request.POST方法获取前端传输的数据
    2、request.POST方法获取的结果为QueryDict,与request.GET获取的结果是样的
    3、一键一值和一键多值的数据处理方式与GET方法完全相同
    """
    data = request.POST
    print(data)                         # <QueryDict: {'user_name': ['zhangsan', 'lisi'], 'password': ['123']}>
    user_name = data['user_name']
    print(user_name)                    # lisi
    user_name = data.get('user_name')
    print(user_name)                    # lisi
    users = data.getlist('user_name')
    print(users)                        # ['zhangsan', 'lisi']
    password = data.get('password')
    print(password)                     # 123
    return HttpResponse('detail-4')

5.3.2 POST json 数据

非表单类型的请求体数据, Django无法自动解析,可以通过 request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON/XML等)进行解析 request.body返 bytes回类型,然后通过decode()解码为JSON形式的字符串数据,再通过json.loads()转换为字典数据,就可使用了。
在这里插入图片描述
在这里插入图片描述

# POST  JSON数据,
def detail5(request, categeory_id, book_id):
    import json
    print(categeory_id, book_id)
    """
    1、json数据的样式,注意:①只能用双引号,不能用单引号。②最好一行数据后面不能加逗号
        {
            "user_name": "zhangsan",
            "password": "123"
        }
    2、通过Ajax发送的JSON数据并没有记录在 request.POST 中,而是记录在 request.body 中
    3、request.body获取到的是bytes类型数据,可以通过decode()转换为JSON形式的str类型,再通过json.loads转换为字典
    4、json模块:
        json.dumps,将字典转换为JSON形式的字符串
        json.loads,将JSON形式的字符串转换为字典
    """
    data = request.POST
    print(data)                         # <QueryDict: {}>
    body = request.body
    print(body)                         # b'{\r\n    "user_name":"zhangsan",\r\n    "password":"123"\r\n}'
    print(type(body))                   # <class 'bytes'>
    body_str = body.decode()            # 对bytes数据解码,结果为str
    print(body_str)                     # {
                                        #     "user_name": "zhangsan",
                                        #     "password": "123"
                                        # }
    print(type(body_str))               # <class 'str'>
    body_dict = json.loads(body_str)    # 将JSON形式的字符串转换为字典
    print(body_dict)                    # {'user_name': 'zhangsan', 'password': '123'}
    print(type(body_dict))              # <class 'dict'>
    return HttpResponse('detail-5')

5.4 http报文头(header) request.META

可以通过 request.META属性获取请求头headers中的数据,request.META为字典类型。
常见的请求头如:

  • CONTENT_LENGTH-The length of the request body (as a string).
  • CONTENT_TYPE-The MIME type of the request body.
  • HTTP ACCEPT-Acceptable content types for the response.
  • HTTP_ACCEPT_ENCODING-Acceptable encodings for the response.
  • HTTP_ACCEPT_LANGUAGE-Acceptable languages for the response.
  • HTTP host-the http host header sent by the client
  • HTTP_REFERER-The referring page, if any
  • HTTP_USER_AGENT-The client’s user-agent string.
  • QUERY_STRING-The query string, as a single (unparsed)string.
  • REMOTE ADDR-The iP address of the client
  • REMOTE HOST The hostname of the client
  • REMOTE_USER-The user authenticated by the Web server, if any.
  • REQUEST METHOD-A string such as "GET"or “POST”
  • SERVER NAME- The hostname of the server.
  • SERVER_PORT-The port of the server (as a string)
    在这里插入图片描述
    在这里插入图片描述
# http报文头(header) request.META
def detail6(request, categeory_id, book_id):
    # print(request.META)
    content_type = request.META['CONTENT_TYPE']
    print(content_type)                 # text/plain
    name = request.META['HTTP_NAME']
    print(name)                         # ruhua

    return HttpResponse('detail-6')

5.5 其他常见HttpRequest对象属性

  • method :一个字符串,表示请求使用的HTP方法,常用值包括:get’pos
  • user:请求的用户对象
  • path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分
  • encoding:一个字符串,表示提交的数据的编码方式
    - 如果为None则表示使用浏览器的默认设置,一般为utf-8
    - 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的 encoding值。
  • FILES:一个类似于字典的对象,包含所有的上传文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
# 其他常见HttpRequest对象属性
def detail7(request, categeory_id, book_id):
    print(request.method)
    return HttpResponse('detail-7')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岳涛@心馨电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值