django学习-29.表单提交方式之一:post请求(注册/登录/改密)

摘要:
单击此链接可成功注销并跳转到登录页面单击该链接可跳转到登录密码修改页面2.1.2。添加新的登录密码{%csrf_token%}用户名:*{error_of_username}}密码:*{error_of_password}2.1.3。新注册页面新用户注册!
目录结构

1.写这篇博客的目的

2.完整操作流程

2.1.第一步:新增相关html页面

2.1.1.新增一个【index_html.html】

2.1.2.新增一个【login_html.html】

2.1.3.新增一个【register_html.html】

2.1.4.新增一个【register_success_html.html】

2.1.5.新增一个【update_password_html.html】

2.1.6.新增一个【update_password_success_html.html】

2.2.第二步:新增相关视图函数

2.2.1.新增一个【indexViews.py】

2.2.2.新增一个【userViews.py】

2.3.第三步:新增url匹配规则

2.4.第四步:重启服务

2.5.第五步:在任一浏览器上面进行相关操作

3.相关知识点

3.1.模板标签【{% csrf_token %}】的作用

3.2.注册密码的加密,和对登录密码和旧密码的密码校验

1.写这篇博客的目的

主要记录表单提交方式post的常见的具体使用;

因为厦门大多数公司项目接口用的都是post表单提交方式,刚好注册接口/登录接口/修改登录密码接口/忘记密码接口的表单提交方式基本都是用post,所以这篇博客里拿注册接口/登录接口/修改登录密码接口这三个接口串联起来讲完整的操作流程;

我们要实现的完整操作流程的步骤大致如下:

  1. 用户通过访问【注册地址】,进到了【注册页面】;
  2. 用户在【注册页面】进行注册,会校验每个提交字段的字段值规则:注册失败会停留在【注册页面】并给出对应错误提示语;注册成功后会跳转到【注册成功提示页面】;
  3. 用户在【注册成功提示页面】点击【返回登录页面的一个链接】,会跳转到【登录页面】;
  4. 用户在【登录页面】进行登录,会校验每个提交字段的字段值规则:登录失败会停留在【登录页面】并给出对应错误提示语;登录成功后会跳转到【后台主页页面】;
  5. 用户在【后台主页页面】点击【退出登录页面的一个链接】,会跳转到【登录页面】;
  6. 用户在【登录页面】进行登录,登录成功后跳转到【后台主页页面】;
  7. 用户在【后台主页页面】点击【修改登录密码的一个链接】,会跳转到【修改登录密码页面】;
  8. 用户在【修改登录密码页面】,会校验每个提交字段的字段值规则:修改登录密码失败会停留在【修改登录密码页面】并给出对应错误提示语;修改登录密码成功后会跳转到【修改登录密码成功页面】;
  9. 用户在【修改登录密码成功页面】点击【返回后台主页页面的一个链接】,会跳转到【后台主页页面】;

细节:

  1. 按照产品文档写的具体需求规则来进行对应流程的操作才是正确的操作;
  2. 要让用户在浏览器输入一个指定的url地址后能访问到一个指定的html页面,结合django的MTV思想,就是这样大致的实现主逻辑:先创建一个html页面,再创建一个视图函数,再创建一个url匹配规则,最后进行调试;
  3. 表单提交方式get和post的各自作用和使用场景,可自行百度,大致了解即可;

完整操作流程可以看接下来的内容;

2.完整操作流程

2.1.第一步:新增相关html页面

按照这样的文件夹分层,新增两个新文件夹【index】和【user】,并新增5个html页面;

django学习-29.表单提交方式之一:post请求(注册/登录/改密)第1张

 2.1.1.新增一个【index_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台主页</title>
</head>
<body>

<p>
    这是后台主页,您可以进行任意业务操作!
    <br>
    <br>
    <a href="{% url 'urlName_of_login' %}">点击这个链接,可以成功退出登录并跳转到登录页面</a>
    <br>
    <a href="{% url 'urlName_of_update_password' %}">点击这个链接,可以跳转到修改登录密码页面</a>
</p>


</body>
</html>

 2.1.2.新增一个【login_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h1>欢迎登录!</h1>
<form action="" method="post">
    {% csrf_token %}
      <p>
        用户名:<input type="text" id="id_username" name="username" required="required"> * {{ error_of_username }}
      </p>
      <p>
         密码:<input type="text" id="id_password" name="password" required="required"> * {{ error_of_password }}
    </p>

    <p>
          <input type="submit" value="登录">
    </p>
</form>

</body>
</html>

 2.1.3.新增一个【register_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>

<body>
<h1>新用户注册!</h1>
<form action="" method="post">
    {% csrf_token %}
    <p>
        用户名:<input type="text" id="id_username" name="username" required="required"> * {{ rename }}
    </p>
    <p>
        密码:<input type="text" id="id_password" name="password" required="required"> *
    </p>
     <p>
       注册邮箱:<input type="text" id="id_mail" name="mail">
    </p>
     <p>
    <input type="submit" value="提交注册信息" >
    </p>
</form>

</body>
</html>

 2.1.4.新增一个【register_success_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册成功页面</title>
</head>
<body>

<p>
    亲爱的用户,恭喜您注册成功!
    <br>
    <br>
    <a href="{% url 'urlName_of_login' %}">点击这个链接,可以跳转到登录页面</a>

</p>


</body>
</html>

2.1.5.新增一个【update_password_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改登录密码页面</title>
</head>
<body>
<h1>请修改您的登录密码!</h1>
<form action="" method="post">
    {% csrf_token %}
      <p>
        用户名:<input type="text" id="id_username" name="username" required="required"> * {{ error_of_username }}
      </p>
      <p>
         旧密码:<input type="text" id="id_old_password" name="old_password" required="required"> * {{ error_of_old_password }}
     </p>
      <p>
         新密码:<input type="text" id="id_new_password" name="new_password" required="required"> * {{ error_of_new_password }}
     </p>

    <p>
          <input type="submit" value="确定">
    </p>
</form>

</body>
</html>

2.1.6.新增一个【update_password_success_html.html】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改登录密码成功页面</title>
</head>
<body>

<p>
    亲爱的用户,恭喜您修改登录密码成功!
    <br>
    <br>
    <a href="{% url 'urlName_of_index' %}">点击这个链接,可以跳转到后台主页页面</a>

</p>


</body>
</html>

2.2.第二步:新增相关视图函数

按照这样的文件夹分层,新增一个新文件夹【views_of_hello】,并新增2个存储视图函数的py文件,两个py文件分别为【indexViews.py】和【userViews.py】;

django学习-29.表单提交方式之一:post请求(注册/登录/改密)第2张

2.2.1.新增一个【indexViews.py】

# coding:utf-8
'''
@file: indexViews.py
@author: 洪景盛
@ide: PyCharm
@createTime: 2021年02月23日  14点59分
@contactInformation: 727803257@qq.com
'''

# 请从这行开始编写脚本
# 在这个py文件里,只存储操作后台主页的所有视图函数
from django.shortcuts import render
from django.http import HttpResponse,Http404
from hello.models import User


def index(request):
    '''用户登录成功后跳转到的后台主页对应的视图函数'''
    return render(request,'index/index_html.html')

2.2.2.新增一个【userViews.py】

# coding:utf-8
'''
@file: userViews.py
@author: 洪景盛
@ide: PyCharm
@createTime: 2021年02月23日  11点02分
@contactInformation: 727803257@qq.com
'''

# 请从这行开始编写脚本

# 在这个py文件里,只存储操作数据表user的所有视图函数
from django.shortcuts import render
from django.http import HttpResponse,Http404,JsonResponse
from hello.models import User
from django.contrib.auth.hashers import make_password,check_password
import re

def register(request):
    '''用户注册页面对应的视图函数'''
    res = ''
    if request.method == 'POST':
        username = request.POST.get('username')  # 用户名
        password = request.POST.get('password')  # 密码
        mail = request.POST.get('mail')  # 注册邮箱
        # 先查询数据库是否已经有这个用户名
        user_list = User.objects.filter(user_name=username)
        if len(user_list) !=0 or user_list:
            # 如果这个用户名已存在,就给个提示
            res = '用户名为【%s】的用户已被注册!'%username
            return render(request, 'user/register_html.html', {"rename":res})
         # 如果这个用户名不存在即还没被注册,就执行新增数据到数据表的操作(涉及到sql新增语句)
        else:
            # 第一种写法(推荐以后都用这种写法)
            user = User()
            user.user_name  = username
            user.user_psw   = make_password(password)
            user.user_email = mail
            user.save()

            # 第二种写法(不推荐)
            # user = User(user_name=username,user_psw=password,user_email=mail)
            # user.save()

            return render(request,'user/register_success_html.html')
    return render(request, "user/register_html.html")

def register_success(request):
    '''用户注册成功后跳转到的注册成功页面对应的视图函数'''
    return render(request,'user/register_success_html.html')


def login(request):
    '''登录页面对应的视图函数'''
    # 第1步:判断请求方式是不是post
    if request.method == 'POST':
        # 第2歩:获取登录页面传给这个视图函数的每个提交字段的字段值
        username = request.POST.get("username")
        password = request.POST.get("password")
        # 第3步:查询用户名是否存在:如果不存在则返回一个用户名相关的错误提示语
        user_list_1 = User.objects.filter(user_name=username)
        if len(user_list_1) == 0:
            error_of_username = '用户名为【%s】的用户不存在,请重新输入!'%username
            return render(request,'user/login_html.html',{"error_of_username":error_of_username})


        # 第4步:校验密码:如果校验不通过则返回一个密码相关的错误提示语;如果校验通过则允许登录成功并跳转到后台主页;
        user_list_2 = User.objects.filter(user_name=username).first()
        is_password_true = check_password(password,user_list_2.user_psw)
        if is_password_true:
            return render(request,'index/index_html.html')
        else:
            error_of_password = '密码错误,请重新输入!'
            return render(request,'user/login_html.html',{"error_of_password":error_of_password})

    else:
        return render(request,"user/login_html.html")


def update_password(request):
    '''修改登录密码页面对应的视图函数'''
    if request.method == 'GET':
        return render(request,"user/update_password_html.html")

    if request.method == 'POST':
        username = request.POST.get("username") # 用户名
        old_password = request.POST.get("old_password") # 旧密码
        new_password = request.POST.get("new_password") # 旧密码

        if len(username)>10:
            error_of_username = '用户名的长度不能超过10'
            # data = {}
            # data["code"] = 100
            # data["success"] = False
            # data["error_of_username"] = error_of_username
            # return JsonResponse(data,json_dumps_params={"ensure_ascii":False})    # 返回一个json串
            return render(request,"user/update_password_html.html",{"error_of_username":error_of_username})
        if len(old_password)>10:
            error_of_old_password = '旧密码的长度不能超过10'
            return render(request,"user/update_password_html.html",{"error_of_old_password":error_of_old_password})
        if len(new_password)>10:
            error_of_new_password = '新密码的长度不能超过10'
            return render(request,"user/update_password_html.html",{"error_of_new_password":error_of_new_password})
        if old_password == new_password:
            error_of_new_password = '新密码不能跟旧密码一样'
            return render(request,"user/update_password_html.html",{"error_of_new_password":error_of_new_password})

        regex = "^[0-9a-zA-Z_]{1,}$"
        if not re.search(regex,old_password):
            error_of_old_password = '旧密码的值只能由数字和英文字母和下划线组成'
            return render(request,"user/update_password_html.html",{"error_of_old_password":error_of_old_password})
        if not re.search(regex,new_password):
            error_of_new_password = '新密码的值只能由数字和英文字母和下划线组成'
            return render(request,"user/update_password_html.html",{"error_of_new_password":error_of_new_password})


        user_list1 = User.objects.filter(user_name=username).values()
        if len(user_list1) == 0:
            error_of_username = '不存在用户名为【%s】的用户'%username
            return render(request,"user/update_password_html.html",{"error_of_username":error_of_username})

        user_list_2 = User.objects.filter(user_name=username).first()
        is_password_true = check_password(old_password,user_list_2.user_psw)

        if not is_password_true:
            error_of_old_password = '旧密码错误,请重新输入'
            return render(request,"user/update_password_html.html",{"error_of_old_password":error_of_old_password})
        else:
            user = User.objects.get(user_name=username)
            user.user_psw = make_password(new_password)
            user.save()
            # return HttpResponse("密码更新成功!")
            return render(request,"user/update_password_success_html.html")

2.3.第三步:新增url匹配规则

在【helloworld/helloworld/urls.py】里新增url匹配规则

django学习-29.表单提交方式之一:post请求(注册/登录/改密)第3张

    #这部分是针对数据表user的所有url匹配规则的汇总=====================================================
     url(r"^user_register_001/$",userViews.register),
     url(r"^user_register_success_001/$",userViews.register_success),
     url(r"^user_login_001/$",userViews.login,name="urlName_of_login"),
     url(r"^user_update_password_001/$",userViews.update_password,name="urlName_of_update_password"),


    #这部分是针对后台主页的所有url匹配规则的汇总=====================================================
     url(r"^index_001/$",indexViews.index, name="urlName_of_index"),

2.4.第四步:重启服务

2.5.第五步:在任一浏览器上面进行相关操作

django学习-29.表单提交方式之一:post请求(注册/登录/改密)第4张

 django学习-29.表单提交方式之一:post请求(注册/登录/改密)第5张

 django学习-29.表单提交方式之一:post请求(注册/登录/改密)第6张

 django学习-29.表单提交方式之一:post请求(注册/登录/改密)第7张

 django学习-29.表单提交方式之一:post请求(注册/登录/改密)第8张

 django学习-29.表单提交方式之一:post请求(注册/登录/改密)第9张

细节:

  1. 在第五步,只记录个人认为重要的相关重要截图,具体调试细节就不具体展开描述;
3.相关知识点

3.1.模板标签【{% csrf_token %}】的作用

模板标签【{% csrf_token %}】的作用:一个html页面里的form标签里的属性action的属性值如果为post,则form标签的内容里必须加上这个模板标签【{% csrf_token %}】,因为可以防止跨站点伪造请求;

CSRF:Cross Site Request Forgery(英文全称),跨站点伪造请求(中文全称)。

举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果某个用户已经登录到这个恶意的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的。

django第一次响应来自某个客户端的请求时,会在服务器端随机生成一个token,把这个token放在cookie里。然后每次POST请求都会带上这个token,这样就能避免被CSRF攻击。

CSRF具体内容大致有这几点(只需要了解概念即可):

  1. 在返回的HTTP响应的cookie里,django会为你添加一个csrftoken字段,其值为一个自动生成的token;
  2. 一个html页面里的form标签里的属性action的属性值如果为post,必须包含一个csrfmiddlewaretoken 字段(只需要在form标签的内容里加上这个模板标签【{% csrf_token %}】,django就会自动帮你生成); 
  3. 在处理POST请求之前,django会验证这个请求的cookie里的csrftoken字段的值和提交的表单里的csrfmiddlewaretoken字段的值是否一样:如果一样,则表明这是一个合法的请求;否则,这个请求可能是来自于别人的csrf攻击,返回【403 Forbidden】;
  4. 在所有ajax方式的POST请求里,添加一个【X-CSRFTOKEN header】,其值为cookie里的csrftoken字段的字段值;

3.2.注册密码的加密,和对登录密码和旧密码的密码校验

出于安全考虑,一般我们都会对注册密码进行加密后才存储到数据表,对登录密码进行密码校验,修改密码时会对旧密码进行密码校验;

django提供了两个方法:make_password,check_password,密码加密用make_password,密码校验用check_password;

涉及到这两个方法的具体相关使用可以看下面的代码内容:

from django.contrib.auth.hashers import make_password,check_password
            user = User()
            user.user_name  = username
            user.user_psw   = make_password(password)
            user.user_email = mail
            user.save()
        user_list_2 = User.objects.filter(user_name=username).first()
        is_password_true = check_password(old_password,user_list_2.user_psw)

        if not is_password_true:
            error_of_old_password = '旧密码错误,请重新输入'
            return render(request,"user/update_password_html.html",{"error_of_old_password":error_of_old_password})
        else:
            user = User.objects.get(user_name=username)
            user.user_psw = make_password(new_password)
            user.save()
            # return HttpResponse("密码更新成功!")
            return render(request,"user/update_password_success_html.html")

django学习-29.表单提交方式之一:post请求(注册/登录/改密)第10张

细节:

  1. 被加密后的密码存储在数据表里不是明文而是密文了; 

免责声明:文章转载自《django学习-29.表单提交方式之一:post请求(注册/登录/改密)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇蜂鸟E203系列——FPGA硬件环境(转)Should 断言的基本使用方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[转] hive0.14-insert、update、delete操作测试

FROM : http://blog.csdn.net/hi_box/article/details/40820341 首先用最普通的建表语句建一个表: [java] view plaincopy  hive>create table test(id int,name string)row format delimited fields ter...

POST提交数据方式

application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。 当直接提交form表单时,默认就使用此种方式。 multipart/form-d...

在SQLSERVER企业管理器中如何创建触发器

下面将分别介绍在MS SQLServer 中如何用SQL Server 管理工具Enterprise Manager 和Transaction_SQL 来创建触发器。在创建触发器以前必须考虑到以下几个方面: CREATE TRIGGER 语句必须是批处理的第一个语句; 表的所有者具有创建触发器的缺省权限,表的所有者不能把该权限传给其它用户; 触发器...

十个PHP开发者最容易犯的错误

文章引用链接:http://www.phpxs.com/post/5974/ PHP 语言让 WEB 端程序设计变得简单,这也是它能流行起来的原因。但也是因为它的简单,PHP 也慢慢发展成一个相对复杂的语言,层出不穷的框架,各种语言特性和版本差异都时常让搞的我们头大,不得不浪费大量时间去调试。这篇文章列出了十个最容易出错的地方,值得我们去注意。 易犯错误...

python测试开发django(8)--django连接mysql

前言 Django对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。本篇以mysql为例简单介绍django连接mysql进行数据操作 Django连mysql需要安装驱动mysqlclient mysqlclient安装 先要安装数据库驱动mysqlclient,使用pip安装就行 pip install...

为网站添加多种语言

首先在项目文件夹下的config\initializers增加一个i18n.rb的文件、i18n是什么、就是英文单词国际化的意思、为了日常方便而简写成i18n、因为这单词一共有20个字母、包括i和n、 1 #encoding: utf-82 I18n.default_locale = :en3 4 LANGUAGES = [5 ['English'...