Django No. 29- 양식 제출 방법 중 하나 : 요청 게시 (등록 / 로그인 / 비밀번호 변경)

1.이 블로그 작성 목적

주로 양식 제출 방법 게시물의 공통적이고 구체적인 사용법을 기록합니다.

Xiamen의 대부분의 회사 프로젝트 인터페이스는 포스트 양식 제출 방법을 사용하기 때문에 등록 인터페이스 / 로그인 인터페이스 / 로그인 비밀번호 인터페이스 변경 / 비밀번호 인터페이스 양식 제출 방법 만 기본적으로 게시되므로이 블로그는 등록 인터페이스 / 로그인 인터페이스를 사용합니다. / change login password interface이 세 인터페이스는 전체 작업 프로세스를 설명하기 위해 직렬로 연결됩니다.

우리가 달성하고자하는 전체 운영 프로세스의 단계는 대략 다음과 같습니다.

  1. 사용자는 [등록 주소]를 방문하여 [등록 페이지]로 들어갑니다.
  2. 사용자가 [등록 페이지]에 등록하면 제출 된 각 필드의 필드 값 규칙이 확인됩니다. 등록에 실패하면 [등록 페이지]에 유지되고 해당 오류 메시지가 표시됩니다. 등록이 성공하면 [등록 성공 프롬프트 페이지]로 이동합니다.
  3. 사용자는 [등록 성공 확인 페이지]에서 [로그인 페이지 링크로 돌아 가기]를 클릭하면 [로그인 페이지]로 이동합니다.
  4. 사용자가 [로그인 페이지]에 로그인하면 제출 된 각 필드의 필드 값 규칙이 확인됩니다. 로그인에 실패하면 [로그인 페이지]에 유지되고 해당 오류 메시지가 표시됩니다. 로그인 성공 후 , [Background Home Page]로 이동합니다;
  5. 사용자는 [Background Home Page]에서 [링크의 로그 아웃 페이지]를 클릭하면 [Login Page]로 이동합니다.
  6. 사용자는 [로그인 페이지]에 로그인하고 로그인이 성공하면 [백그라운드 홈 페이지]로 이동합니다.
  7. 사용자는 [백그라운드 홈 페이지]에서 [로그인 비밀번호 수정 링크]를 클릭하면 [로그인 비밀번호 수정 페이지]로 이동합니다.
  8. 사용자는 [로그인 비밀번호 수정 페이지]에서 제출 된 각 필드의 필드 값을 확인합니다. 규칙 : 로그인 비밀번호 수정에 실패 할 경우 [로그인 비밀번호 수정 페이지]에 남아 있으며 해당 오류 메시지를 표시합니다. 로그인 암호가 성공적으로 수정되면 [Modify login password success page]로 이동합니다.
  9. 사용자는 [로그인 비밀번호 변경 성공 페이지]에서 [백엔드 홈 페이지로 돌아 가기]를 클릭하면 [백엔드 홈 페이지]로 리디렉션됩니다.

세부 묘사:

  1. 올바른 작업은 제품 문서에 기록 된 특정 요구 사항 규칙에 따라 해당 프로세스 작업을 수행하는 것입니다.
  2. 사용자가 브라우저에 지정된 url 주소를 입력하고 django의 MTV 아이디어와 결합하여 지정된 html 페이지에 액세스 할 수 있도록하기 위해 기본 로직은 대략 다음과 같이 구현됩니다. 먼저 html 페이지를 생성 한 다음보기 기능을 생성 한 다음 A를 생성합니다. URL 일치 규칙, 그리고 마지막으로 디버깅;
  3. 양식 제출 방법 가져 오기 및 게시의 각 기능 및 사용 시나리오는 Baidu에서 직접 이해할 수 있습니다.

전체 운영 프로세스는 다음 내용에서 볼 수 있습니다.

 

둘째, 완전한 운영 프로세스

1. 첫 번째 단계 : 관련 HTML 페이지 추가

이 폴더 계층 구조에 따라 두 개의 새 폴더 [index] 및 [user]를 추가하고 5 개의 html 페이지를 추가합니다.

 1.1. 새 [index.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>

 1.2. 새 [login.html] 추가

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>登录页面</title>

</head>

<body>

<h1>欢迎登录!</h1>

<form action="" method="post">

    {% csrf_token %}

    <p>

        用户名:<label for="id_username"></label><input type="text" id="id_username" name="username" required="required">

        * {
   
   { error_of_username }}

    </p>

    <p>

        密码:<label for="id_password"></label><input type="text" id="id_password" name="password" required="required">

        * {
   
   { error_of_password }}

    </p>



    <p>

        <input type="submit" value="登录">

    </p>

</form>



</body>

</html>

 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>

        用户名:<label for="id_username"></label><input type="text" id="id_username" name="username" required="required">

        * {
   
   { rename }}

    </p>

    <p>

        密码:<label for="id_password"></label><input type="text" id="id_password" name="password" required="required"> *

    </p>

    <p>

        注册邮箱:<label for="id_mail"></label><input type="text" id="id_mail" name="mail">

    </p>

    <p>

        <input type="submit" value="提交注册信息">

    </p>

</form>



</body>

</html>

 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>

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>

        用户名:<label for="id_username"></label><input type="text" id="id_username" name="username" required="required">

        * {
   
   { error_of_username }}

    </p>

    <p>

        旧密码:<label for="id_old_password"></label><input type="text" id="id_old_password" name="old_password"

                                                        required="required"> * {
   
   { error_of_old_password }}

    </p>

    <p>

        新密码:<label for="id_new_password"></label><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>

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]입니다.

2.1. 새 [indexViews.py] 추가

#!/usr/bin/python

# -*- coding:utf-8 -*-



"""""""""""""""""""""""""""""""""

@file: userViews.py

@author: lucas

@createTime: 2021/3/9 5:53 下午

@Function: 存储后台主页的所有视图函数

"""""""""""""""""""""""""""""""""



# 用户登录成功后跳转到的后台主页对应的视图函数

from django.shortcuts import render





def index(request):

    return render(request, 'index/index.html')

 

2.2. 새 [userViews.py] 추가

#!/usr/bin/python

# -*- coding:utf-8 -*-



"""""""""""""""""""""""""""""""""

@file: userViews.py

@author: lucas

@createTime: 2021/3/9 5:53 下午

@Function: 存储后台主页的所有视图函数

"""""""""""""""""""""""""""""""""



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', {"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')

    return render(request, "user/register.html")





def register_success(request):

    '''用户注册成功后跳转到的注册成功页面对应的视图函数'''

    return render(request, 'user/register_success.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', {"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')

        else:

            error_of_password = '密码错误,请重新输入!'

            return render(request, 'user/login.html', {"error_of_password": error_of_password})



    else:

        return render(request, "user/login.html")





def update_password(request):

    '''修改登录密码页面对应的视图函数'''

    if request.method == 'GET':

        return render(request, "user/update_password.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", {"error_of_username": error_of_username})

        if len(old_password) > 10:

            error_of_old_password = '旧密码的长度不能超过10'

            return render(request, "user/update_password.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", {"error_of_new_password": error_of_new_password})

        if old_password == new_password:

            error_of_new_password = '新密码不能跟旧密码一样'

            return render(request, "user/update_password.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", {"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", {"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", {"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", {"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")

붙여진:

관련 지식 포인트 :

템플릿 태그의 역할 [{% csrf_token %}]

템플릿 태그 [{% csrf_token %}]의 기능 : HTML 페이지의 양식 태그에서 속성 액션의 속성 값이 post 인 경우이 템플릿 태그 [{% csrf_token %}]를 콘텐츠에 추가해야합니다. 양식 태그는 사이트 간 위조 된 요청을 방지 할 수 있기 때문입니다.

CSRF : 교차 사이트 요청 위조 (전체 영어 이름), 교차 사이트 위조 요청 (전체 중국어 이름).

예를 들어 악성 웹 사이트에 귀하의 웹 사이트에 대한 링크가 있습니다. 사용자가 악성 웹 사이트에 로그인 한 경우 사용자가 악성 웹 사이트의 링크를 클릭하면 웹 사이트에서 요청을 보낼 때 귀하의 웹 사이트는 사용자가 요청을 보낸 것으로 간주 할 것이며 실제로 요청은 악성 웹 사이트에 의해 위조 된 것입니다.

Django가 클라이언트의 요청에 처음으로 응답하면 서버 측에서 무작위로 토큰을 생성하고이 토큰을 쿠키에 넣습니다. 그런 다음 모든 POST 요청은 CSRF 공격을 피하기 위해이 토큰을 가져옵니다.

CSRF의 구체적인 내용은 대략 다음과 같은 점을 가지고 있습니다 (개념을 이해하기 만하면됩니다).

  1. 반환 된 HTTP 응답의 쿠키에서 django는 자동 생성 된 토큰 인 csrftoken 필드를 추가합니다.
  2. HTML 페이지의 양식 태그에있는 속성 작업의 속성 값이 post 인 경우 csrfmiddlewaretoken 필드를 포함해야합니다 (이 템플릿 태그 [{% csrf_token %}]를 양식 태그의 내용에 추가하면 django가 자동으로 생성하는 데 도움이됩니다. 
  3. POST 요청을 처리하기 전에 django는 요청 쿠키의 csrftoken 필드 값이 제출 된 양식의 csrfmiddlewaretoken 필드 값과 동일한 지 여부를 확인합니다. 동일하면 이것이 합법적임을 나타냅니다. 그렇지 않으면 다른 사람의 csrf 공격에서 요청이 될 수 있습니다. return [403 Forbidden];
  4. 모든 ajax POST 요청에서 값이 쿠키에있는 csrftoken 필드의 필드 값인 [X-CSRFTOKEN 헤더]를 추가하십시오.

2.3. 3 단계 : URL 일치 규칙 추가

[helloworld / helloworld / urls.py]에 URL 일치 규칙 추가

  #这部分是针对数据表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 단계 4 : 여기에 세부 변경 사항이 있습니다. 원래 데이터베이스 암호 필드의 길이가 너무 짧습니다.

 

2.5. 4 단계 : 서비스 다시 시작

2.6. 5 단계 : 모든 브라우저에서 관련 작업 수행

 

 

 

 

 

 

 

 

 

 

 

 

 

 

추천

출처blog.csdn.net/LYX_WIN/article/details/114777257