视图介绍、URLconf配置、路由命名、reverse反解析、PostMan测试、HttpRequest对象、URL路径参数、QueryDict对象、查询字符串、请求体、请求头、HttpRequest

重点

  • HttpRequest
    • 位置参数和关键字参数
    • 查询字符串
    • 请求体:表单数据,JSON数据
    • 请求头
  • HttpResponse

    • HttpResponse

    • JsonResponse

    • redirect

  • 类视图

    • 类视图的定义和使用

    • 类视图装饰器(难点)

一、视图介绍和项目准备

1.1 视图介绍
  • 视图就是应用views.py文件中的函数
  • 视图的第一个参数必须为HttpRequest对象,还可能包含下参数如
    • 通过正则表达式组获取的位置参数
    • 通过正则表达式组获得的关键字参数
  • 视图必须返回一个HttpResponse对象子对象作为响应
    • 子对象: JsonResponse HttpResponseRedirect
  • 视图负责接受Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者
    • 响应内容可以是HTML内容404错误重定向json数据...
  • 视图处理过程如下图:

使用视图时需要进行两步操作,两步操作不分先后

  1. 配置URLconf
  2. 应用/views.py中定义视图

项目准备

  • 创建项目+创建应用+安装应用+配置模板路径+本地化+mysql数据库+URLconf+视图

  • mysql数据库使用之前的book2

DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',
        # 'NAME': BASE_DIR / 'db.sqlite3',

        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': '123456',  # 数据库用户密码
        'NAME': 'book2'  # 数据库名字
    }
}
  • URLconf
    • settings.py中:指定url配置

      ROOT_URLCONF = 'bookmanager.urls'

    • 项目中urls.py:只要不是admin/就匹配成功,包含到应用中的urls.py

      from django.contrib import admin
      from django.urls import path, include
      
      urlpatterns = [
          path('admin/', admin.site.urls),
          # 把子路由信息添加到总路由中,只要不是‘admin/’就匹配成功,包含到应用中的urls.py
          path('', include('book.urls')),  # 使用include来将子应用book里的全部路由包含进工程路由中
      ]
  • 应用中urls.py:匹配bookls/成功就调用views中的bookList函数,测试项目逻辑

    from django.urls import path
    from book.views import bookList
    
    urlpatterns = [
        # 匹配书籍列表信息的URL,调用对应的bookList视图
        path('bookls/', bookList),
    ]
  • 视图:测试项目逻辑

    from django.http import HttpResponse
    
    # Create your views here.
    # 定义视图:提供书籍列表信息
    def bookList(request):
    
        return HttpResponse('OK!')

  • 在models.py 文件中定义模型类

    from django.db import models
    
    # Create your models here.
    from django.db import models
    
    # Create your models here.
    # 准备书籍列表信息的模型类
    class BookInfo(models.Model):
        # 创建字段,字段类型...
        name = models.CharField(max_length=20, verbose_name='名称')
        pub_date = models.DateField(verbose_name='发布日期',null=True)
        readcount = models.IntegerField(default=0, verbose_name='阅读量')
        commentcount = models.IntegerField(default=0, verbose_name='评论量')
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    
        class Meta:
            db_table = 'bookinfo'  # 指明数据库表名
            verbose_name = '图书'  # 在admin站点中显示的名称
    
        def __str__(self):
            """定义每个数据对象的显示信息"""
            return self.name
    
    # 准备人物列表信息的模型类
    class PeopleInfo(models.Model):
        GENDER_CHOICES = (
            (0, 'male'),
            (1, 'female')
        )
        name = models.CharField(max_length=20, verbose_name='名称')
        gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
        description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
        book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    
        class Meta:
            db_table = 'peopleinfo'
            verbose_name = '人物信息'
    
        def __str__(self):
            return self.name

  • 以下过程不再演示,已在django模型、项目、配置、模型类、数据库操作、查询、F/Q对象、字段类型、聚合函数、排序函数博文中完成

    • 1)生成迁移文件

      python manage.py makemigrations
      

      2)同步到数据库中

      python manage.py migrate
      

      3)添加测试数据

      insert into bookinfo(name, pub_date, readcount,commentcount, is_delete) values
      ('射雕英雄传', '1980-5-1', 12, 34, 0),
      ('天龙八部', '1986-7-24', 36, 40, 0),
      ('笑傲江湖', '1995-12-24', 20, 80, 0),
      ('雪山飞狐', '1987-11-11', 58, 24, 0);
      
      insert into peopleinfo(name, gender, book_id, description, is_delete)  values
          ('郭靖', 1, 1, '降龙十八掌', 0),
          ('黄蓉', 0, 1, '打狗棍法', 0),
          ('黄药师', 1, 1, '弹指神通', 0),
          ('欧阳锋', 1, 1, '蛤蟆功', 0),
          ('梅超风', 0, 1, '九阴白骨爪', 0),
          ('乔峰', 1, 2, '降龙十八掌', 0),
          ('段誉', 1, 2, '六脉神剑', 0),
          ('虚竹', 1, 2, '天山六阳掌', 0),
          ('王语嫣', 0, 2, '神仙姐姐', 0),
          ('令狐冲', 1, 3, '独孤九剑', 0),
          ('任盈盈', 0, 3, '弹琴', 0),
          ('岳不群', 1, 3, '华山剑法', 0),
          ('东方不败', 0, 3, '葵花宝典', 0),
          ('胡斐', 1, 4, '胡家刀法', 0),
          ('苗若兰', 0, 4, '黄衣', 0),
          ('程灵素', 0, 4, '医术', 0),
          ('袁紫衣', 0, 4, '六合拳', 0);

二、URLconf配置

  • 浏览者通过在浏览器的地址栏中输入网址请求网站
  • 对于Django开发的网站,由哪一个视图进行处理请求,是由url匹配找到的
配置URLconf
  • 1.settings.py

    • 指定url配置

      ROOT_URLCONF = '项目.urls'
      
  • 2.项目中urls.py

    • 匹配成功后,包含到应用的urls.py

      path(正则, include('应用.urls'))
      
  • 3.应用中urls.py

    • 匹配成功后,调用views.py对应的函数

      path(正则, views.函数名)
      
  • 4.提示

      1. 正则部分推荐使用 r,表示字符串不转义,这样在正则表达式中使用 \ 只写一个就可以
    
      2. 不能在开始加反斜杠,推荐在结束加反斜杠
          正确:path/
          正确:path
          错误:/path
          错误:/path/
    
      3. 请求的url被看做是一个普通的python字符串,进行匹配时不包括域名、get或post参数
          3.1 如请求地址如下:
              http://127.0.0.1:8000/18/?a=10
          3.2 去掉域名和参数部分后,只剩下如下部分与正则匹配
              18/
    

说明:虽然路由结尾带/能带来上述好处,但是却违背了HTTP中URL表示资源位置路径的设计理念。是否结尾带/以所属公司定义风格为准。

三、路由命名与reverse反解析(逆向)

1 路由命名

在定义路由的时候,可以为路由命名,方便查找特定视图的具体路径信息。

1) 在使用include函数定义路由时,可以使用namespace参数定义路由的命名空间,如

path('',include('book.urls',namespace='book'))

命名空间表示,凡是book.urls中定义的路由,均属于namespace指明的book名下。

命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。

2) 在定义普通路由时,可以使用name参数指明路由的名字,如

from django.urls import path
from book.views import bookList, testproject

app_name = 'book'
urlpatterns = [
    # 匹配书籍列表信息的URL,调用对应的bookList视图
    path('bookls/', bookList, name='index'),
    path('testproject/', testproject, name='test')
]
2 reverse反解析

使用reverse函数,可以根据路由名称,返回具体的路径,如:

from django.core.urlresolvers import reverse
#或者
from django.urls import reverse

def testproject(request):

    return HttpResponse("OK")

# 定义视图:提供书籍列表信息
def bookList(request):

    url = reverse('book:test')
    print(url)
    return HttpResponse('index')

  • 对于未指明namespace的,reverse(路由name)
  • 对于指明namespace的,reverse(命名空间namespace:路由name)

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

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

  • 安装方式1:去 Chrome 商店直接搜索 PostMan 扩展程序进行安装
  • 安装方式2:Postman API Platform官网下载桌面版
  • 安装方式3:将已下载好的 PostMan 插件文件夹拖入到浏览器

下载桌面版

下载安装后,打开如下

五、HttpRequest对象

回想一下,利用HTTP协议向服务器传参有几种途径?

  • 提取URL的特定部分,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取;
  • 查询字符串(query string),形如key1=value1&key2=value2;
  • 请求体(body)中发送的数据,比如表单数据、json、xml;
  • 在http报文的头(header)中。
1 URL路径参数
  • 如果想从URL中获取值,需要在正则表达式中使用分组
  • 获取值分为两种方式
    • 位置参数
      • 参数的位置不能错
    • 关键字参数
      • 参数的位置可以变,跟关键字保持一致即可
  • 注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式
  • 分别使用以上两种获取URL值的方式提取出18 188
    • http://127.0.0.1:8000/18/188/
  • 应用中urls.py

  • 视图中函数: 参数的位置不能错

    path('<int:value1>/<int:value2>/', index),
  • def index(request, value1, value2):
        # 构造上下文
        context = {'v1': value1, 'v2': value2}
        return render(request, 'index.html', context)

2 Django中的QueryDict对象

HttpRequest对象的属性GET、POST都是QueryDict类型的对象

与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况

  • 方法get():根据键获取值

    如果一个键同时拥有多个值将获取最后一个值

    如果键不存在则返回None值,可以设置默认值进行后续处理

    get('键',默认值)
    
  • 方法getlist():根据键获取值,值以列表返回,可以获取指定键的所有值

    如果键不存在则返回空列表[],可以设置默认值进行后续处理

    getlist('键',默认值)
    
3. 查询字符串Query String

获取请求路径中的查询字符串参数(形如?k1=v1&k2=v2),可以通过request.GET属性获取,返回QueryDict对象。

# /get/?a=1&b=2&a=3
# 即:http://127.0.0.1:8000/get/?a=1&b=2&a=3

def get(request):
    a = request.GET.get('a')
    b = request.GET.get('b')
    alist = request.GET.getlist('a')
    print(request.GET)  # <QueryDict: {'a': ['1', '3'], 'b': ['2']}>
    print(a)  # 3
    print(b)  # 2
    print(alist)  # ['1', '3']
    return HttpResponse('OK')

重要:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。

4 请求体

请求体数据格式不固定,可以是表单类型字符串,可以是JSON字符串,可以是XML字符串,应区别对待。

可以发送请求体数据的请求方式有POSTPUTPATCHDELETE

Django默认开启了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制,方法为在settings.py文件中注释掉CSRF中间件,如:

注释后

4.1 表单类型 Form Data

前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。

def post(request):
    a = request.POST.get('username')
    b = request.POST.get('password')
    alist = request.POST.getlist('username')
    print(request.POST)
    print(a)
    print(b)
    print(alist)
    return HttpResponse('OK')
4.2 非表单类型 Non-Form Data

非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。request.body返回bytes类型。

例如要获取请求体中的如下JSON数据

{"a": 1, "b": 2}

可以进行如下方法操作:

import json

def post_json(request):
    json_str = request.body
    print('request.body为:', json_str)  #request.body为: b'{\r\n    "username":"xqnav.top",\r\n    "password":"123456"\r\n}'
    json_str = json_str.decode()  # python3.6 无需执行此步,json形式的字符串
    print('json_str为:', json_str, '类型为:', type(json_str))
    # json_str为: {
    #     "username": "xqnav.top",
    #     "password": "123456"
    # }
    # 类型为: <class 'str'>
    req_data = json.loads(json_str)
    # json.dumps:将字典转换为json形式的字符串
    # json.loads:将json形式的字符串转换为字典
    print('req_data为:', req_data)   # req_data为: {'username': 'xqnav.top', 'password': '123456'}
    print(req_data['username'])   # xqnav.top
    print(req_data['password'])   # 123456
    return HttpResponse('OK')

 

5 请求头

可以通过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).

具体使用如:

def get_headers(request):
    print(request.META)
    print(request.META['CONTENT_TYPE'])
    print(request.method)
    return HttpResponse('OK')

 

6 其他常用HttpRequest对象属性
  • method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。
  • user:请求的用户对象。
  • path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
  • encoding:一个字符串,表示提交的数据的编码方式。

    • 如果为None则表示使用浏览器的默认设置,一般为utf-8。
    • 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
  • FILES:一个类似于字典的对象,包含所有的上传文件。

六、HttpResponse对象

视图在接收请求并处理后,必须返回HttpResponse对象或子对象。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。

1 HttpResponse

可以使用django.http.HttpResponse来构造响应对象。

HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)

也可通过HttpResponse对象属性来设置响应体、响应体数据类型、状态码:

  • content:表示返回的内容。
  • status_code:返回的HTTP响应状态码。

响应头可以直接将HttpResponse对象当做字典进行响应头键值对的设置:

response = HttpResponse()
response['django'] = 'Python'  # 自定义响应头django, 值为Python

示例:

from django.http import HttpResponse

def response(request):
    return HttpResponse('django python', status=400)
    或者
    response = HttpResponse('django python')
    response.status_code = 400
    response['django'] = 'Python'
    return response

2 HttpResponse子类

Django提供了一系列HttpResponse的子类,可以快速设置状态码,状态码范围100~599

  • HttpResponseRedirect 301
  • HttpResponsePermanentRedirect 302
  • HttpResponseNotModified 304
  • HttpResponseBadRequest 400
  • HttpResponseNotFound 404
  • HttpResponseForbidden 403
  • HttpResponseNotAllowed 405
  • HttpResponseGone 410
  • HttpResponseServerError 500
3 JsonResponse

若要返回json数据,可以使用JsonResponse来构造响应对象,作用:

  • 帮助我们将数据转换为json字符串
  • 设置响应头Content-Typeapplication/json
from django.http import JsonResponse

def response(request):
    return JsonResponse({'city': 'beijing', 'subject': 'python'})

 

4 redirect重定向
from django.shortcuts import redirect

def response(request):
    return redirect('/2/220/')


学习导航:http://www.xqnav.top

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

learning-striving

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

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

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

打赏作者

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

抵扣说明:

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

余额充值