Python(五十五)状态保持以及表单
从2021年9月2日发文至今,Python系列(包括代码在内)共计106125个字、五十五篇!
1. session(会话)保存状态
1.http协议是无状态的:每次请求都是一次新的请求,不会记得之前通信的状态。
2.客户端与服务器端的一次通信,就是一次会话实现状态保持的方式:在客户端或服务器端存储与会话有关的数据。
3.存储方式包括cookie、session,会话一般指session对象。
4.使用cookie,所有数据存储在客户端,注意不要存储敏感信息。
5.使用sesison方式,所有数据存储在服务器端,在客户端cookie中存储session_id。
6.状态保持的目的是在一段时间内跟踪请求者的状态,可以实现跨页面访问当前请求者的数据。
- 注意:不同的请求者之间不会共享这个数据,与请求者一一对应。
![](https://img.haomeiwen.com/i26973252/00198e60233b89c4.png)
1.1. 使用session
启用会话后,每个HttpRequest对象将具有一个session属性,它是一个类字典对象
- get(key, default=None):根据键获取会话的值
- flush():删除当前的会话数据并删除会话的Cookie
1.2.会话过期时间
- set_expiry(value):设置会话的超时时间
- 如果没有指定,则两个星期后过期
- 如果value是一个整数,会话将在values秒没有活动后过期
- 若果value是一个imedelta对象,会话将在当前时间加上这个指定的日期/时间过期
- 如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期
- 如果value为None,那么会话永不过期
form_session/views.py:
from django.shortcuts import render
from django.views import View
from django.shortcuts import redirect,reverse
# Create your views here.
def home(request):
# 从session里面去获取相关与username的值,通过username变量去接收,如果没有值,将”用户未登录“的字符串赋值给username
username = request.session.get('username','用户未登录')
if username == '用户未登录':
return redirect('login') # 这里重定向可以不写reverse
return render(request,'form_session/home.html',context={
'username':username
})
class LoginTest(View):
def get(self,request):
return render(request,'form_session/login.html')
def post(self,request):
username = request.POST.get('user') # 这里和模板文件login第一个input里的name值保持一致
request.session['username'] = username # 保存用户登录状态
request.session.set_expiry(0) # 0表示关闭浏览器后过期
return redirect(reverse('home')) # 如果渲染页面,需要携带数据用render,简单的页面跳转用重定向
def logout(request):
request.session.flush() # 删除当前会话的数据并删除cookie
return redirect('home')
form_session/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('home/',views.home,name='home'),
path('login/',views.LoginTest.as_view(),name='login'),
path('logout/',views.logout,name='logout'),
]
templates/form_session/login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录页面</title>
</head>
<body>
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<input type="text" placeholder="请输入用户名" name="user"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
templates/form_session/home.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
欢迎{{ username }}登录页面 {# 这里的username是views里context传的键 #}
<a href="{% url 'logout' %}">注销</a>
</body>
</html>
注: 使用session之前需要先执行makemigrations,migrate的模型映射文件命令,在数据库中有生成django_session的表格。
2. django的form表单
2.1. form表单的引用
登录页面和注册页面都会用到form表单来提交数据,当数据提交到后台后, 需要在视图函数中去验证数据的合法性,而django中提供了一个form表单的功能, 这个表单可以用来验证数据的合法性还可以用来生成HTML代码。
2.2. form表单的使用
1.创建一个forms.py的文件,放在指定的app当中,然后在里面写表单。
2.表单是通过类实现的,继承自forms.Form,然后在里面定义要验证的字段。
3.在表单中,创建字段跟模型是一模一样的,但是没有null=True或者blank=True等这几种参数了,有的参数是required=True/False。
4.使用is_valid()方法可以验证用户提交的数据是否合法,而且HTML表单元素的name必须和django中的表单的name保持一致,否则匹配不到。
5.is_bound属性:用来表示form是否绑定了数据,如果绑定了,则返回True,否则返回False。
6.cleaned_data:这个是在is_valid()返回True的时候,保存用户提交上来的数据。
2.3. form表单例子
可以生成前端页面,也可以用来验证数据的合法性。
form_session/forms.py:
from django import forms
class RegisterForm(forms.Form):
# 用户名,默认情况下是text文本框
username = forms.CharField(max_length=30,min_length=4,
widget=forms.TextInput(attrs={'placeholder':'请输入用户名'})
)
# 密码,这里要将文本框改成密码框
password = forms.CharField(max_length=16,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请输入密码'})
)
# 确认密码
password_confirm = forms.CharField(max_length=16,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请再次输入密码'})
)
# 邮箱
email = forms.EmailField()
2.4. form表单中的参数
max_length:最大长度
min_length:最小长度
widget:负责渲染网页上HTML 表单的输入元素和提取提交的原始数据
attrs:包含渲染后的Widget 将要设置的HTML 属性
error_messages:报错信息
注:虽然form可以生成前端页面,但这个功能实际用的少,主要是是用form表单的验证功能。
2.5. 注册的视图函数
form_session/views.py:
# 但凡是后台都需要写在视图函数里进行获取,而不能直接写在模板文件里
from .forms import RegisterForm
from .models import UserModel
from django.http import HttpResponse
from django.shortcuts import render,redirect,reverse
from django.views import View
class RegisterTest(View):
def get(self,request):
form = RegisterForm()
return render(request,'form_session/register.html',context={'form':form})
def post(self,request):
form = RegisterForm(request.POST) # 获取表单的所有数据
if form.is_valid(): # 判断数据是否合法,True表示合法,这里的合不合法主要指邮箱@后的格式
# 保存用户提交的数据
username = form.cleaned_data.get('username')
pwd = form.cleaned_data.get('password')
pwd_confirm = form.cleaned_data.get('password_confirm')
email = form.cleaned_data.get('email')
if pwd == pwd_confirm:
# 两次密码保持一致,则保存
UserModel.objects.create(username=username,password=pwd,email=email)
return HttpResponse('注册成功!欢迎您使用该网站')
else:
return HttpResponse('注册失败!请确认两次密码输入一致!')
else:
return HttpResponse('请输入合法的数据!')
templates/form_session/register.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册页面</title>
</head>
<body>
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
{#后台传输过来的数据需要在前端进行显示,使用的是模板变量#}
{% comment %} {# 默认是内联标签,都在同一行进行显示 #}
{{ form }}{% endcomment %}
{# 以p标签单独成行进行显示 #}
{{ form.as_p }}
<input type="submit" value="注册">
</form>
</body>
</html>
3. 登录注册案例
form_session/forms.py:
# (十一、状态保持以及表单:form表单)
from django import forms
class RegisterForm(forms.Form):
# 用户名,默认情况下是text文本框
username = forms.CharField(max_length=30,min_length=4,
widget=forms.TextInput(attrs={'placeholder':'请输入用户名'})
)
# 密码,这里要将文本框改成密码框
password = forms.CharField(max_length=16,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请输入密码'})
)
# 确认密码
password_confirm = forms.CharField(max_length=16,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请再次输入密码'})
)
# 邮箱
email = forms.EmailField()
# (十二、中间件和上下文处理器)
from django import forms
class LoginForm(forms.Form):
# 用户名,默认情况下是text文本框
username = forms.CharField(max_length=30,min_length=4,
widget=forms.TextInput(attrs={'placeholder':'请输入用户名'})
)
# 密码,这里要将文本框改成密码框
password = forms.CharField(max_length=16,min_length=6,
widget=forms.PasswordInput(attrs={'placeholder':'请输入密码'})
)
form_session/views.py:
# 但凡是后台都需要写在视图函数里进行获取,而不能直接写在模板文件里
from .forms import RegisterForm
from .models import UserModel
from django.http import HttpResponse
from django.shortcuts import render,redirect,reverse
from django.views import View
class RegisterTest(View):
def get(self,request):
form = RegisterForm()
return render(request,'form_session/register.html',context={'form':form})
def post(self,request):
form = RegisterForm(request.POST) # 获取表单的所有数据
if form.is_valid(): # 判断数据是否合法,True表示合法,这里的合不合法主要指邮箱@后的格式
# 保存用户提交的数据
username = form.cleaned_data.get('username')
pwd = form.cleaned_data.get('password')
pwd_confirm = form.cleaned_data.get('password_confirm')
email = form.cleaned_data.get('email')
if pwd == pwd_confirm:
# 两次密码保持一致,则保存
UserModel.objects.create(username=username,password=pwd,email=email)
return HttpResponse('注册成功!欢迎您使用该网站')
else:
return HttpResponse('注册失败!请确认两次密码输入一致!')
else:
return HttpResponse('请输入合法的数据!')
# (十二、中间件和上下文处理器)
from .forms import LoginForm
from .models import UserModel
from django.http import HttpResponse
from django.shortcuts import render,redirect,reverse
from django.views import View
class Db_Login(View):
def get(self,request):
form = LoginForm()
return render(request,'form_session/db_login.html',context={
'form':form
})
def post(self,request):
form = LoginForm(request.POST)
if form.is_valid(): # 判断数据是否合法,True表示合法
# 保存用户提交的数据
username = form.cleaned_data.get('username')
pwd = form.cleaned_data.get('password')
user = UserModel.objects.filter(username=username,password=pwd) # 如果用get,找不到user就会报错,所以用filter更好
if user:
# 如果有这个用户
request.session['username'] = username
return redirect(reverse('home'))
else:
return HttpResponse('登录失败!用户名或密码输入有误')
else:
return HttpResponse('请输入合法的数据!')
templates/form_session/register.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册页面</title>
</head>
<body>
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
{#后台传输过来的数据需要在前端进行显示,使用的是模板变量#}
{% comment %} {# 默认是内联标签,都在同一行进行显示 #}
{{ form }}{% endcomment %}
{# 以p标签单独成行进行显示 #}
{{ form.as_p }}
<input type="submit" value="注册">
</form>
</body>
</html>
templates/form_session/db_login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录页面</title>
</head>
<body>
<form action="{% url 'dblogin' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="登录">
</form>
</body>
</html>
templates/form_session/home.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
欢迎{{ username }}登录页面 {# 这里的username是views里context传的键 #}
<a href="{% url 'logout' %}">注销</a>
</body>
</html>
form_session/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('register/',views.RegisterTest.as_view(),name='register'),
path('dblogin/',views.Db_Login.as_view(),name='dblogin'),
]
文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!
Editor:Lonelyroots