Django 基础:请求与响应

请求

简介

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

  • 提取 URL 的特定部分,如 /weather/beijing/2018,可以在服务器端的路由中用正则表达式截取。
  • 查询字符串(Query),形如key1=value1 & key2=value2
  • 请求体(Body)中发送的数据,比如表单数据,json, xml
  • 在 HTTP 报文头(header )中
URL 路径参数

在定义路由 URL 时,可以使用正则表达式提取参数的方法从 URL 中获取请求参数,Django 会将提取的参数直接传递到视图的传入参数中。

  • 未命名参数按定义顺序传递,如:
url(r'^weather/([a-z]+)/(\d{4})/$', views.weather)
def weather(request, city, year):
    print("city=%s" % city)
    print("year=%s" % year)
    return HttpResponse("OK")
  • 命名参数按名字传递,如:
url(r'weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.weather)
def weather(request, year, city):
    print("city=%s" % city)
    print("year=%s" % year)
    return HttpResponse("OK")
Django 中的 QueryDict 对象

定义在 django.http.QueryDict,HttpRequest 对象的属性 GET,POST都是 QueryDict 类型的对象,与 Python 字典不同,QueryDict 类型的对象用来处理同一个键带多个值的情况

方法
  • get():根据键获取值
    如果一个键同时拥有多个值将获取最后一个值
    如果键不存在则返回None值,可以设置默认值进行后续处理
dict.get('键', 默认值)
可简写dict['键']
  • getlist():根据键获取值,值以列表返回,可以获取指定键的所有值
    如果键不存在则返回空列表[],可以设置默认值进行后续处理
dict.getlist('键', 默认值)
查询字符串 Query String

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

# /qs/?a=1&b=2&a=3

def qs(request):
     a = request.GET.get('a')
     b = request.GET.get('b')
    alist = request.GET.getlist('a')

    print(a)
    print(b)
    print(alist)
    return HttpResponse("OK")

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

请求体
简介

请求体数据格式不固定,可以是表单类型字符串,可以是 JSON 字符串,可以是 XML 字符串,应区别对待。
可以发送请求体数据的请求方式有 POST, PUT, PATCH, DELETE。
Django 默认开启了 CSRF 防护,会对上述请求进行 CSRF 防护验证,在测试时可以关闭 CSRF 防护机制,方法为在 settings.py 文件中注释掉 CSRF 中间件。

表单类型 Form Data

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

def get_body(request):
    a = request.POST.get('a')
    b = request.POST.get('b')
    alist = request.POST.getlist('a')
    print(a)
    print(b)
    print(alist)
    return HttpResponse('OK')

注意:request.POST 只能用来获取 POST 方式的请求体表单数据

非表单类型 Non-Form Data

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

import json

def get_body_json(request):
    json_str = request.body
    json_str = json_str.decode()  # python3.6 无需执行此步
    req_data = json.loads(json_str)
    print(req_data['a'])
    print(req_data['b'])
    return HttpResponse("OK")
请求头

可以通过 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['CONTENT_TYPE'])
    return HttpResponse('OK')
其他常用 HttpRequest 对象属性
  • method:一个字符串,表示请求使用的 HTTP 方法,常用值包括:‘GET’,'POST'
  • user: 请求的用户对象
  • path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
  • encoding:一个字符串,表示提交的数据的编码方式。
  • FILES:一个类似于字典的对象,包含所有的上传文件。

响应

简介

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

HttpResponse

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

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

也可通过 HttpResponse 对象属性来设置响应体,状态码:

  • content:表示返回的内容。
  • status_code:返回的 HTTP 响应状态码。
    响应头可以直接将 HttpResponse 对象当做字典进行响应头键值对的设置:
response = HttpResponse()
response['Itcast'] = 'Python'  # 自定义响应头 Itcast ,值为 Python

实例:

from django.http import HttpResponse

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

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

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

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

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

def demo_view(request):
    return JsonResponse({'city': 'beijing', 'subject': 'python'})
redirect 重定向
from django.shortcuts import redirect

def demo_view(request):
    return redirect('/index.html')

Cookie

简介

Cookie, 有时也用其复数形式 Cookies,指某些网站为了辨别用户身份,进行 session 跟踪而存储在用户本地终端上的数据(通常经过加密)。Cookie 最早是网景公司的前雇员 Lou Montulli 在 1993 年 3 月的发明。Cookie 是由服务器端生成,发送给 User-Agent(一般是浏览器),浏览器会将 Cookie 的 key/value 保存到某个目录下的文本文件内,下次请求同一网站时就发送该 Cookie 给服务器(前提是浏览器设置为启用 cookie)。Cookie 名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等。服务器可以利用 Cookies 包含信息的任意性来筛选并经常性维护这些信息,以判断在 HTTP 传输中的状态。Cookies 最典型记住用户名。

Cookie 是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用。

特点
  • Cookie 以键值对的格式进行信息的存储
  • Cookie 基于域名安全,不同域名的 Cookie 是不能互相访问的,如访问 itcast.cn 时向浏览器中写了 Cookie 信息,使用同一浏览器访问 baidu.com 时,无法访问到 itcast.cn 写的 Cookie 信息。
  • 当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有 Cookie 信息提交给网站服务器。
设置

可以通过 HttpResponse 对象中的 set_cookie 方法来设置 cookie。

HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
  • max_age 单位是秒,默认为None。如果是临时 cookie ,可将 max_age 设置为 None

实例:

def demo_view(request):
    response = HttpResponse("OK")
    response.set_cookie('itcast1', 'python1')
    response.set_cookie('itcast1', 'python2', max_age=3600)
    return response
读取

可以通过 HttpRequest 对象的 COOKIES 属性来读取本次请求携带的 cookie 值。request.COOKIES 为字典类型。

def demo_view(request):
    cookie1 = request.COOKIES.get("itcast1")
    print(cookie1)
    return HttpResponse("OK")

Session

启用 Session

Django 项目默认是启用 Session
可以在 settings.py 文件中查看
如需禁用 session,将上图中的 session 中间件注释掉即可。

存储方式

在 settings.py 中,可以设置 session 数据的存储方式,可以保存在数据库,本地缓存等。

数据库

存储在数据库中,如下设置可以写,也可以不写。这是默认存储方式。

SESSION_ENGINE = 'django.contrib.session.backends.db'

如果存储在数据库中,需要向 INSTALLED_APPS 中安装 Session 应用。
数据库中的表,表结构如下
由表结构可知,操作 Session 包括三个数据,键,值,过期时间。

本地缓存

存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
混合存储

优先从本机内存中存取,如果没有则从数据库中存取

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
Redis

在 redis 中保存 session,需要引入第三方扩展,我们可以使用 django-redis 来解决

  • 安装扩展
pip install django-redis
  • 配置,在 settings.py 文件中作如下设置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cahce.RedisCache",
        "LOCATION": "redis:/'/127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": ”django_redis.client.DefaultClient“,
        }
    }
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

如果 Redis 的ip 地址不是本地回环 127.0.0.1,而是其他地址,访问 Django 时,可能出现 Redis 连接错误。
解决方案:修改 Redis 的配置文件,添加特定的 ip 地址。

打开 Redis 的配置文件

sudo vim /etc/redis/redis.conf

修改完成后,重启 Redis 服务

sudo  service redis-server restart
操作

通过 HttpRequest 对象的 session 属性进行会话的读写操作

  • 以键值对的格式写 session
request.session['键'] = 值
  • 根据键读取值
request.session.get("键", 默认值)
  • 清除所有 session ,在存储中删除值部分
request.session.clear()
  • 清除 session 数据,在存储中删除 session 的整条数据。
request.session.flush()
  • 删除session 中指定的键和值,在存储中只删除某个键及值
del request.session['键']
  • 设置 session 的有效期
request.session.set_expiry(value)

如果 value 是一个整数,session 将在 value 秒没有活动后过期。
如果 value 为 0,那么用户 session 的 Cookie 将在用户的浏览器关闭时过期。
如果 value 为 None,那么 session 有效期将采用系统默认值,默认为两周,可以通过在 settings.py 中设置 SESSION_COOKIE_AGE 来设置全局默认值。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容