Python(五十四)cookie与session
从2021年9月2日发文至今,Python系列(包括代码在内)共计103089个字、五十四篇!
小知识科普:
在pycharm的Terminal中安装模块如果出现这个问题:
ModuleNotFoundError: No module named 'pip'
(或者各种各样的问题),我建议先采用这种方式来安装库,因为我的python解释器是在F:\learning_records\SoftwareSpace\Python3.7
这个路径下方的,所以我在Windows的cmd命令行窗口用这种方式(如下图):F:\learning_records\SoftwareSpace\Python3.7>python.exe -m pip install requests [-i https://pypi.douban.com/simple]
:中括号内的为国内镜像源,可以加快速度,可用可不用。
如果遇到这种
ImportError:cannot import name 'views'
的问题,不妨先看下右上角的运行文件名称,修改下即可!
大家知道客户端和服务器是怎么记录登录状态的呢?
如果你不知道,那请阅读这篇文章,因为它将带你走近并解决这个问题!
1.HttpRequest对象
服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,视图函数的第一个参数是HttpRequest对象在django.http模块中定义了HttpRequest对象的API。
2.GET和POST请求
get_post/views.py:
# (十、cookie与session)
import os
from django.shortcuts import render
from django.http import HttpResponse,JsonResponse
from django.views import View
from Myblog15_16.settings import MEDIA_ROOT
# Create your views here.
def index(request):
print(request)
print(request.path) # 路由
print(request.method) # 提交方式
print(request.encoding) # 编码为None,则为浏览器的默认编码
print(request.get_host()) # ip加端口
print(request.get_port()) # 端口
return render(request,'get_post/index.html')
# get一般用于渲染页面
def get_test(request):
print(request.method)
# user = request.GET.get('user')
# pwd = request.GET.get('pwd') # get方法只能用于一对一获取值
# print(user,pwd)
hobbies = request.GET.getlist('hobby') # getlist方法可以用于一对多获取值
print(hobbies)
return HttpResponse('数据提交成功!')
# post一般用于数据提交,相比于get更加地安全!
def post_test(request):
print(request.method)
user = request.POST.get('user')
pwd = request.POST.get('pwd')
print(user,pwd)
return HttpResponse('数据提交成功!')
{#(十、cookie与session)#}
{% comment %}{#get测试#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求与响应</title>
</head>
<body>
<form action="{% url 'get_test' %}" method="get">
<input type="text" name="user" placeholder="请输入用户名"><br>
<input type="password" name="pwd" placeholder="请输入密码"><br>
<button type="submit">提交</button>
</form>
</body>
</html>{% endcomment %}
{% comment %}{#post测试#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求与响应</title>
</head>
<body>
<form action="{% url 'post_test' %}" method="post">
{% csrf_token %}
<input type="text" name="user" placeholder="请输入用户名"><br>
<input type="password" name="pwd" placeholder="请输入密码"><br>
<button type="submit">提交</button>
</form>
</body>
</html>{% endcomment %}
3.类视图
View类视图以请求方式为类方法:在对应的方式下面编写对应的逻辑函数。
blog/views.py:
# (十、cookie与session:类视图)
from django.views import View
from .models import BlogModel
from django.shortcuts import render, redirect, reverse
# 使用类视图,可以不需要get和post判断
class Blog_update(View):
def get(self,request,blog_id):
blog = BlogModel.objects.get(id=blog_id)
return render(request,'blog/blog_edit.html',context={'blog':blog})
def post(self,request,blog_id):
# 获取文章标题
new_title = request.POST.get('new_title') # 这里的new_title需要和前端页面blog_edit里的标题input中的name值保持一致.
# 获取文章内容
new_content = request.POST.get('new_content') # 这里的new_content需要和前端页面blog_edit里的内容input中的name值保持一致.
BlogModel.objects.filter(id=blog_id).update(title=new_title,content=new_content) # 这里的红变量名是数据库中的字段名称
# 文章修改成功后,要转到文章列表页,展示所有文章.
return redirect(reverse('blog_list'))
templates/blog/blog_edit.html:
{% extends 'blog/blog_base.html' %}
{% block title %}
修改博客
{% endblock %}
{% block body %}
<h1>修改博客</h1>
{% comment %} <form action="{% url 'blog_edit' blog.id %}" method="post"> {% endcomment %} {# 当不填写action提交路径时,默认提交到当前路径,所以这里写不写action都是可以的 #}
<form action="{% url 'cls_update' blog.id %}" method="post"> {# (十、cookie与session:类视图) #}
{# csrf_token防止跨域请求 #}
{% csrf_token %}
新标题:<input type="text" id="new_title" name="new_title" value="{{ blog.title }}"><br>
新内容:<textarea name="new_content" id="new_content" cols="20" rows="10">{{ blog.content }}</textarea>
<button type="submit">确认修改</button>
</form>
<br>
<a href="{% url 'blog_list' %}">返回列表页</a>
{% endblock %}
templates/blog/blog_list.html:
{% extends 'blog/blog_base.html' %}
{% block title %}
博客显示
{% endblock %}
{% block body %}
<h1>靓文展示页</h1>
<table>
<tr>
<th width="80px">标题</th>
<th>功能</th>
</tr>
{% for b in b_list %}
<tr>
<td style="text-align: center"><a href="{% url 'blog_detail' b.id %}">{{ b.title }}</a></td>
{% comment %} <td><a href="{% url 'blog_edit' b.id %}">编辑</a> <a href="{% url 'blog_delete' b.id %}">删除</a></td>{% endcomment %}
<td><a href="{% url 'cls_update' b.id %}">编辑</a> <a href="{% url 'blog_delete' b.id %}">删除</a></td> {# (十、cookie与session:类视图) #}
</tr>
{% endfor %}
</table>
<br>
<a href="{% url 'blog_index' %}">返回首页</a>
{% endblock %}
get_post/urls.py:
# (十、cookie与session)
from django.urls import path
from . import views
urlpatterns = [
path('index/',views.index),
path('get_test/',views.get_test,name='get_test'),
path('post_test/',views.post_test,name='post_test'),
path('upload/',views.Upload.as_view(),name='upload'),
path('json_test/',views.json_test,name='json_test'),
]
View类视图的引用:在url.py中配置路由是通过as_view()
blog/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('index/',views.index,name='blog_index'),
path('cls_update/<blog_id>/',views.Blog_update.as_view(),name='cls_update'), # 只要是使用类视图,就需要调用as_view()这个方法
]
4.文件上传
Django在处理文件上传的时候,文件数据被保存在了request.FILES
FILES中的每个键为<input type="file" name="" />中的name
设置文件的存储路径:
1.在项目根目录下static中创建media文件夹
2.图片上传后,会被保存到“/static/media/文件”
3.打开settings.py文件,增加media_root项
4.1.文件上传form表单中
FILES只有在请求的方法为POST且提交的<form>带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象。
templates/get_post/index.html:
{#文件上传#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>请求与响应</title>
</head>
<body>
<form action="{% url 'upload' %}" method="post" enctype="multipart/form-data"> {# enctype="multipart/form-data"如果不设置,默认不允许文件上传 #}
{% csrf_token %}
<input type="text" name="user" placeholder="请输入用户名"><br>
<input type="password" name="pwd" placeholder="请输入密码"><br>
<input type="file" name="file"><br>
<button type="submit">提交</button>
</form>
</body>
</html>
4.2.文件上传视图函数
get_post/views.py:
# (十、cookie与session)
import os
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from Myblog15_16.settings import MEDIA_ROOT
# 文件上传类视图
class Upload(View):
def get(self,request):
return render(request,'get_post/index.html')
def post(self,request):
# 获取文件需要使用FILES的方法
f = request.FILES.get('file') # 获取文件
f_name = os.path.join(MEDIA_ROOT,f.name) # 拼接路径和文件名
with open(f_name,'wb+') as fp:
for i in f.chunks(): # 读取文件的内容,
# read()是从文件中读取整个上传的数据,如果文件过大,就会读到内存中,占用系统内存
# chunks()如果上传的文件足够大时,就会分块上传数据
fp.write(i)
return HttpResponse('文件上传完毕!')
5.HttpResponse对象
5.1.HttpResponse的子类:
返回数据的响应函数有:
HttpResponse() 返回简单的字符串对象
render() 渲染模板
redirect() 重定向
JsonResponse() 返回json数据
其中JsonResponse:
- 帮助用户创建JSON编码的响应
- 参数data是字典对象
- JsonResponse的默认Content-Type为application/json
get_post/views.py:
# (十、cookie与session)
from django.http import JsonResponse
def json_test(request):
# JSON格式的数据必定是双引号
return JsonResponse({'name':'chenhong','age':18}) # 这里是键值对的字典,通过路由在网页上访问时,才是一个JSON格式的数据
6.Http协议
HTTP(超文本传输协议)是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型,且HTTP是一个无状态的协议。
7.浏览器中的cookie
虽然cookie可以保存状态,但注意不要存储敏感信息。想要了解状态保持的另一种方式,请关注Python系列(五十五)的内容哦!
注意:设置cookie值以及删除cookie值都是response对象的操作,而获取cookie是从requeset相应中获得的.
get_post/views.py:
import datetime
from django.http import HttpResponse
# 设置cookie
def set_ck(request):
response = HttpResponse('设置cookie')
# response.set_cookie('name','django') # 不设置过期时间的情况下,关闭浏览器就过期了
# response.set_cookie('name','django',max_age=30) # 设置过期时间,以秒为单位,30s后过期
response.set_cookie('name','django',expires=datetime.datetime(2022,2,25)) # 指定过期时间
return response
# 获取cookie
def get_ck(request):
ck = request.COOKIES
value = ck.get('name')
if value:
return HttpResponse(f'欢迎{value}回来!')
return HttpResponse('请您先登录')
# 删除cookie
def del_ck(request):
response = HttpResponse('删除cookie')
response.delete_cookie('name')
return response
get_post/urls.py:
# (十、cookie与session)
from django.urls import path
from . import views
urlpatterns = [
path('set_ck/',views.set_ck,name='set_ck'),
path('get_ck/',views.get_ck,name='get_ck'),
path('del_ck/',views.del_ck,name='del_ck'),
]
文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!
Editor:Lonelyroots