Django请求,响应cookie,session

常心水
2023-12-01

1.请求与相应

1.HTTP协议向服务器传参的4中途径——

​ 1.请求行中的路径即URL中的特定部分

​ 2.查询字符串

​ 3.请求体

​ 4.请求头

2.使用正则提取URL中参数——

​ 2.1位置参数——

url(r'^weather/([a-z]+)/(\d{4})/$', views.weather),
# URL去传递参数——通过正则表达式实现传参
# 获取URL路径中的数据,使用小括号方式  例如:/([a-z]+)/(\d+)
# 使用小括号传递的参数是位置参数,需要和视图函数里面的顺序相对应
def weather(request, city, year):
    # 读取正则中的组提取的参数
    print('city=%s' % city)
    print('year=%s' % year)
    return HttpResponse('OK')

​ 2.2关键字参数——

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')
3.提取查询字符串参数——QueryDict

​ 3.1需求:提取问号后面的查询字符串

例如:/weather3/beijing/?a=10&b=20&a=30

​ 3.2 通过request.GET属性获取请求路径中的查询字符串参数,返回QueryDict对象

# /qs/?a=1&b=2&a=3
# get():根据键获取值
def qs(request):
    a = request.GET.get('a')
    b = request.GET.get('b')
    alist = request.GET.getlist('a')
    print(a)  # 3
    print(b)  # 2
    print(alist)  # ['1', '3']
    return HttpResponse('OK')
   
# 目标:演示获取url中查询参数/查询字符数据
# weather/beijing/2018/?a=10&b=10&a=30
# GET: /get_query_par/
# request下的两种属性:GET 和 POST  说明:GET和POST是属性,返回的是QueryDict对象  get和post为浏览器的请求方式
def request_response(request):
    # get获取的是一键一值,但是获取的是最后一个数据
    # print(request.GET.get('a'))  # a = 30
    # # getlist获取的是一键多值
    # print(request.GET.getlist('a')) # a = 10
    # print(request.GET.get('b'))
    # # return http.HttpResponse('request_response')
    # return http.HttpResponse('ok')


    # 这里既可以用POST模式也可以用GET模式 但是获取元素都是用get或getlist
    print(request.POST.get('a'))
    print(request.POST.getlist('a'))
    print(request.POST.get('b'))
    return http.HttpResponse('request_response')

​ 3.3.get()方式读取一个键一个值,获取最后一个值

​ getlist()方式读取一个键多个值,返回列表

# /qs/?a=1&b=2&a=3
# get():根据键获取值
def qs(request):
    a = request.GET.get('a')
    b = request.GET.get('b')
    alist = request.GET.getlist('a')
    print(a)  # 3
    print(b)  # 2
    print(alist)  # ['1', '3']
    return HttpResponse('OK')
    
# 目标:演示获取url中查询参数/查询字符数据
# weather/beijing/2018/?a=10&b=10&a=30
# GET: /get_query_par/
# request下的两种属性:GET 和 POST  说明:GET和POST是属性,返回的是QueryDict对象  get和post为浏览器的请求方式
def request_response(request):
    # get获取的是一键一值,但是获取的是最后一个数据
    # print(request.GET.get('a'))  # a = 30
    # # getlist获取的是一键多值
    # print(request.GET.getlist('a')) # a = 10
    # print(request.GET.get('b'))
    # # return http.HttpResponse('request_response')
    # return http.HttpResponse('ok')


    # 这里既可以用POST模式也可以用GET模式 但是获取元素都是用get或getlist
    print(request.POST.get('a'))
    print(request.POST.getlist('a'))
    print(request.POST.get('b'))
    return http.HttpResponse('request_response')

4.提取请求体中的参数——

​ 1.请求体数据格式不固定,表单,json字符串,XML

​ 2.发送请求体的请求方式:POST,PUT,PATCH,DELETE

4.1提取请求体中的表单数据——

​ 1.通过request.POST属性获取,返回Query.Dict类型的对象

# 目标: 演示获取请求体表单数据 request.POST
# POST /get_form_data/
# 在提取form表单数据时,需要把限制解除 在settings.py文件中MIDDLEWARE关闭CSRF防护
# 得到表单数据——用到调试工具Postman
# 在发送数据栏  如果应用路由后面有/,需要在发送数据的时候也要带上/
# 发送表单数据,选择Body下的form-data
# def post_form_data(request):
#     print(request.POST)
#     query_dict = request.POST
#     # query_dict.dict()  # 如果需要删除表单数据,query_dict.dict() 将QueryDict类型转换成普通的字典格式——dict
#     return http.HttpResponse('post_form_data')

# 获取请求体中的表单数据
def get_form_data(request):
    a = request.POST.get('name')
    # a.dict('name')
    print(a)
    b=request.POST.get('age')
    print(b)
    return http.HttpResponse('get_form_data')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BjHPlY2G-1587286520055)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1577072440806.png)]

注意:request.POST只能用来获取POST方式的请求体表单数据(没有权限被拒绝,CSRF中间件注释掉)
4.2非表单数据——

​ 1.通过request.body属性获取原始请求体数据

​ 2.request.body返回bytes类型

# 目标: 演示获取请求体中的非表单数据(json,xml)  request.body
# POST: /get_json_data/
# 获取非表单数据的第一步: request.body获取bytes类型的数据
#  第二步:将bytes类型数据转换成str类型  用decode()
#  第三步:把str类型的数据转换成json数据(字典类型)——json.load()
# def post_no_form_data(request):
#     data_bytes = request.body  # request.body获取的是bytes类型的数据
#     json_str = data_bytes.decode()  # 将bytes类型转换成str类型
#     dict1 = json.loads(json_str)  # 把str类型的数据转换成json数据(字典类型) "{'name': 'zs'}"  ---> {'name': 'zs'}
#     print(dict1)
#     # json.loads((request.body.decode()))
#     return http.HttpResponse('post_no_form_data')

# 获取请求体中的非表单数据(json,html)——request.body
def get_noform_data(request):
    str = request.body.decode()
    dict = json.loads(str)
    print(dict['name'])
    print(dict['age'])
    return http.HttpResponse('get_noform_data')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BnjGwIkU-1587286520058)(C:\Users\86155\AppData\Roaming\Typora\typora-user-images\1577073371650.png)]

5.提取请求头中的信息——

​ 1.通过request.META属性获取请求头headers中的数据

​ 2.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).

​ 5.1语法结构——

def get_headers(request):
    print(request.META['CONTENT_TYPE'])
    return HttpResponse('OK')
6.其他请求报文信息——
method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。
user:请求的用户对象。
path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
encoding:一个字符串,表示提交的数据的编码方式。
如果为None则表示使用浏览器的默认设置,一般为utf-8。
这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
FILES:一个类似于字典的对象,包含所有的上传文件

​ 6.1语法结构

print(request.method, request.path)

2.响应对象

1.HttpResponse——

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

HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
# 注意:响应体参数必须传
return HttpResponse('OK',content_type='text/html',status=200)

​ 1.2 也可以通过HttpResponse对象属性来设置响应体和状态码

# 创建相应对象
response = HttpResponse('OK',content_type='text/html',status=200)
# 自定义响应头:键值对形式  键:Itcast  值:Python
response['Itcast'] = 'Python'
return response
from django.http import HttpResponse
def demo_view(request):
    return HttpResponse('itcast python', status=400)
    或者
    response = HttpResponse('itcast python',status=400)
    response.status_code = 400
    response['Itcast'] = 'Python'
    return response
    
# 演示响应对象基本操作
#  GET  /httpresponse_data/
# def httpresponse_data(request):
#     # return http.HttpResponse(content='响应体',content_type='响应体类型',status='状态码')
#     response = http.HttpResponse(content='httpresponse_data',content_type='text/html',status=200) # 200必须为int类型  不能是字符串
#
#     print(response.content) # 得到的数据是响应体 但是把响应体转换成为bytes类型
#     print(response.status_code) # 得到的状态码
#
#     # 自定义响应头
#     response['itcast'] = 'heima'
#     return response
2.JsonResponse——

​ 1.使用JsonResponse来构造响应对象,返回json数据

# GET /response_json/ (表示⽤用户向我们索取json) 
def response_json(request):    
    """响应json数据"""
    # 准备字典:json字符串的key,需要双引号    
	json_dict = {"name":"zxj", "age":2.5}    
    # 默认会设置状态码    
    # 默认会将数据类型设置为 Content-Type: application/json    
    # 默认会将json字典转json字符串串,再将json字符串串转⼆二进制响应给⽤用户    
	return JsonResponse(json_dict)

# 演示响应json数据
# 如果响应的json数据  一般选用JsonResponse响应
# 1.将数据转换成json字符串
# 2.设置响应体类型为application/json
# def jsonresponse_data(request):
#     # json响应的数据一般默认为字典类型,如果非要响应列表,需要把json里面的safe改为False模式
#     data = ['A']
#     data1 = {
#         "name":"lisi",
#         "age":18
#     }
#     return JsonResponse(data1,safe=False)


# 2.JsonResponse来构造响应对象  返回json数据
# json数据一般默认是字典类型
# 如果要响应列表类型  需要在后面加safe=False
def json_response(request):
    dict1={
        'name':'lisi',
        'age':18
    }
    list1=['A','B','C']
    return JsonResponse(data=list1,safe=False)
3.重定向——redirect
# GET /response_redirect/ 
def response_redirect(request):    
"""重定向"""
# 需求:重定向到users应⽤用的index视图    
# 使⽤用最原始的⽅方式    
# return redirect('/users/index/')    
# 使⽤用反向解析实现重定向    
return redirect(reverse('users:index'))


# 演示重定向
# 第一步  需要导包——redirect
# def redirect_data(request):
# 其实内部的运行是判断当前用户是否登录,如果登录就响应用户中心界面
# 如果没有响应登录,就重定向到lpl
# 显示的结果就是lpl函数下的内容:釜底抽薪
# 在写重定向的路由时,lpl前面的/一定要写上  如果不写 会变成redirect_data/lpl/
# 1.redirect(函数名)
# return redirect('/lpl/') # 首先是人为的去发送请求redirect_data  因为是redirect重定向  浏览器会自动发送请求/lpl/
# 2.redirect(路由别名)
#return redirect('abc')
# 3.redirect('命名空间:路由别名')
# 如果给路由起命名空间 那么上面1,2就不会执行了
# return redirect('users:abc')

# 3.重定向
def drict(request):
    return redirect('/json_response/')
    # return http.HttpResponse('hello direct')
1.客户端给服务器传参的途径:
  • 提取URL路径的特定部分:(get, post, put, delete) 利用正则组(?P)
  • 查询字符串: (get) :使用请求对象 GET
  • 请求体(表单: 用请求对象的 POST属性, 非表单): (post, put):
  • 请求头
###3. [重点]提取URL路径后面携带的参数
  • 正则位置参数提取URL路径参数
    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路径参数
  • 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')
    
4. [重点]查询字符串(query string)
  • QueryDict介绍(支持一个键带多个值)

    • Request.GET.get(‘键’, 默认值)
    • Request.GET.getlist(‘键’, 默认值)
  • 提取URL查询参数

    • 请求路径:?k1=v1&k2=v2&k1=v3

    • 获取:

      • request.GET.get('k1', "")
        request.GET.get('k2', "")
        request.GET.getlist('k1', [])
        
  • 注意:查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。

5. [重点]请求体(body)中传递的参数—form表单数据
  • 提取form表单步骤:
    • 1.Django中关闭CSRF防护
    • 2.request.POST属性获取(QueryDict对象)
  • 注意:request.POST只能获取POST方式请求体表单数据
  1. [重点]请求体(body)中传递的参数—非表单数据
  • 提取非表单数据步骤:
    • 1.request.body属性获取最原始的请求体数据(bytes)
    • 2.把bytes转换成str(decode())
    • 3.把json_str转换成字典dict = json.loads(json_str)
    • 4.把列表字典转化为json字符串json_str = json.dumps()
  1. [了解]请求头-传递参数&其他常用HttpRequest对象的属性使用
  • 提取请求头
    • request.META属性获取请求头数据(python字典类型)
      • CONTENT_TYPE
  • 其他常用HttpRequest对象属性
    • method
    • user
    • path
    • encoding
      • None (utf-8)
    • FILES
  1. [了解]HttpResponse响应对象
  • 构造响应对象
    • HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
    • 对象属性:content、status_code
  • 设置响应头
    • response[‘Itcast’] = ‘python’
  • 其他子类
    • HttpResponseRedirect 301
    • HttpResponseNotFound 404
  1. [重点]JsonResponse响应对象
  • 作用:
    • 数据转换成json字符串
    • 设置响应头Content-Type 为 application/json
10.[重点]redirect重定向
  • # 演示重定向
    # redirect既可以重定向,又可以反向解析
    # 第一步  需要导包——redirect
    def redirect_data(request):
        # 其实内部的运行是判断当前用户是否登录,如果登录就响应用户中心界面
        # 如果没有响应登录,就重定向到lpl
        # 显示的结果就是lpl函数下的内容:釜底抽薪
        # 在写重定向的路由时,lpl前面的/一定要写上  如果不写 会变成redirect_data/lpl/
        # 1.redirect(函数名)
        # return redirect('/lpl/') # 首先是人为的去发送请求redirect_data  因为是redirect重定向  浏览器会自动发送请求/lpl/
        # 2.redirect(路由别名)
        return redirect('abc')
        # 3.redirect('命名空间:路由别名')
        # 如果给路由起命名空间 那么上面1,2就不会执行了
        # return redirect('users:abc')
    
11.[了解]Cookie的介绍&理解
  • 介绍:
    • Cookie是存储在浏览器中的一段纯文本信息(最典型记住用户名),建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用。
  • 特点:
    • key-value存储
    • 基于域名安全,不同域名的Cookie是不能互相访问的
12.Cookie代码实现——设置cookie通过响应对象 读取的时候通过请求对象
  • 设置Cookie

    • response.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
      
    • 注意:max_age(秒),默认None(当前会话结束)

  • 读取Cookie

    • request.COOKIES(字典类型)
  • 扩展:删除cookie

    • response.delete_cookie(cookie名)
      
def cookie_data(request):
    response =http.HttpResponse('cookie_data')
    # HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
    # cookie存储的是key-value
    # 如果max_age=0 则表示删除cookie 如果为None,表示会话结束,清除cookie
    data = response.set_cookie(key='name',value='ssj',max_age=None)
    data1 = request.COOKIES.get('name') # 得到对应的cookie值
    print(data1)
    return response
  • Session 的作用

    session的存和取都是通过请求对象而不是响应对象的原因:

    # 1.session存储在服务端,响应是给浏览器传数据
    # 2.session依赖cookie  而cookie是存储在请求对象中,
    
    • 状态保持,保存用户登录信息,以键值对方式保存用户信息到服务器 通过配置将内容存储到redis数据库`。
  • Cookie和Session的对比

    • Cookie是存储在浏览器端的用户状态信息
    • Session是存储在web服务器端的用户状态信息
  • Session的特点

    • 依赖cookies
    • 存储敏感、重要的信息
    • 支持更多字节
    • Session共享问题
03-[了解]session配置和存储
  • 安装扩展

    • pip install django-redis
      
  • settings配置文件

    • # 指定session存储方案——存储在cache中,这里会出现不能共享问题,因此修改为RedisCache
      SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
      SESSION_CACHE_ALIAS = "default"  # 表示连接哪个redis数据库
      
      # 指定Django缓存配置
      CACHES = {
          "default": {
              # 这里需要安装一个django_redis的模块
              "BACKEND": "django_redis.cache.RedisCache",  # 缓存后端
          # 这里是连接redis的IP地址 端口号  以及是第几个数据库(redis有16个数据库,因此可以写16个)
              "LOCATION": "redis://192.168.103.210:6379/1",
              "OPTIONS": {
                  "CLIENT_CLASS": "django_redis.client.DefaultClient",
              }
          }
      }
      
  • 注意:如果提示链接失败

    • sudo vim /etc/redis/redis.conf
      	修改 -》 bind 127.0.0.1 自己的ip
      sudo service redis-server restart
      or
      sudo redis-server /etc/redis/redis.conf
      
04-[重点]session代码实现session设置和读取
  • 设置session:

    • request.session["key"] = "value"
      
  • 获取session:

    • request.session.get("key", "")
      
  • 删除session:

  • # 方法1 根据key清除value
    	del request.session["like"]
    # 方法2 清除所有数据——清除所有键值对
       request.session.clear()
    
    session的存储位置
    # 1.session存在mysql数据库中,读写速度慢
    # 2.session存在cache服务器内存条中,读写速度快  但是多个服务器之间没法共享 因此
    # 3.session存在redis缓存中
    
  • 拓展:

  • # 设置过期时长,默认是:2个星期过期
    # 参数:过期的秒数
       request.session.set_expiry(3600)
      
    # 删除整条记录——删除整个session数据
    	request.session.flush()
    
注意点:
# Http协议无状态
COOKIE和SESSION区别:
1. 相同点: 都可以用来做状态保持,会话(一次响应,一次请求)状态保持, 都可以缓存数据
2. 不同点:
    COOKIE 它缓存的数据在客户端(浏览器), 存储长度有限最大4kb, 在浏览器上同一个域名最多只能存20个cookie, 直接是明文可以见,数据不安全
    SESSION 它缓存在服务器, 存储长度没有限制, 数据更加安全

设置/修改cookie  response.set_cookie(key, value, max_age=过期时间)  过期时间必须是int类型  设置cookie时把cookie包装在响应头 Set-cookie
获取cookie   request.COOKIES.get('key')  请求头 Cookie

"""
# # 演示session缓存
# def session_data(requset):
#     # session缓存 是存储在服务器的内存条cache中,但是会出现共享问题,需要把数据存储在redis中
#     # 第一步:安装django_redis模块
#     # 第二步:设置存储方案——SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
#     # 第三步:指定缓存配置——主要是两个地方
#     # BACKEND": "django_redis.cache.RedisCache",  # 缓存后端
#     # "LOCATION": "redis://127.0.0.1:6379/1",
#     # 第四步:指定缓存哪个数据库  这里是数据库1
#     # key存在为修改,不存在为新建
#     # session首先把{'name':'zhangsan'} 转换成字符串类型存储在redis中,然后在进行字符串的拼接,构成sessionid 作为redis的key值
#     # requset.session['name']='zhangsan' # 当新建session时,会生成一个sessionid值,把值存储到cookie中
#     # 获取session
#     print(requset.session.get('name')) # 这里得到的数据类型为字符串
#     return http.HttpResponse('session_data')
    # session依赖cookie——主要是依赖cookie的sessionid 当删除浏览器里面的cookie时,再次调用就会报错
    # session的过期时间不设置或默认为None 时间默认是两周
    # session过期时间如果为0  表示会话结束就删除
session弊端:

​ 1.依赖cookie;

​ 2.数据是存储在后端(会占用后端缓存)
“django_redis.cache.RedisCache”, # 缓存后端

# “LOCATION”: “redis://127.0.0.1:6379/1”,

# 第四步:指定缓存哪个数据库 这里是数据库1

# key存在为修改,不存在为新建

# session首先把{‘name’:‘zhangsan’} 转换成字符串类型存储在redis中,然后在进行字符串的拼接,构成sessionid 作为redis的key值

# requset.session[‘name’]=‘zhangsan’ # 当新建session时,会生成一个sessionid值,把值存储到cookie中

# 获取session

print(requset.session.get(‘name’)) # 这里得到的数据类型为字符串

return http.HttpResponse(‘session_data’)

# session依赖cookie——主要是依赖cookie的sessionid 当删除浏览器里面的cookie时,再次调用就会报错
# session的过期时间不设置或默认为None 时间默认是两周
# session过期时间如果为0  表示会话结束就删除

###### session弊端:

​	1.依赖cookie;

​	2.数据是存储在后端(会占用后端缓存)

​	3.集成服务器群会出现共享资源的问题
 类似资料: