Django 2.0 项目实战 (3): 用户重置密码与退出登录

在之前两篇文章中我们扩展了Django自带的User模型并实现了用户的登录与注册,并同时实现了查看和编辑用户个人资料的功能。本文是Django实现用户注册登录系列教程的最后一篇,我们将会开发两个功能页面,一个允许用户在登录后重置密码,一个是退出登录。本文代码用Django 2.0 + Python 3.X编写。


第一步 重温models.py和urls.py


模型Models设计是Django Web开发的第一步,更多信息见Django 2.0 Web开发核心技术之Models设计

# users/models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.


class UserProfile(models.Model):

   user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')

   org = models.CharField(
       'Organization', max_length=128, blank=True)

   telephone = models.CharField(
       'Telephone', max_length=50, blank=True)

   mod_date = models.DateTimeField('Last modified', auto_now=True)

   class Meta:
       verbose_name = 'User Profile'

   
def __str__(self):
       return "{}".format(self.user.__str__())


如果你不知道下面URL的含义, 请点击这里

# users/urls.py

from django.urls import re_path
from . import views

app_name = 'users'
urlpatterns = [
   re_path(r'^register/$', views.register, name='register'),
   
re_path(r'^login/$', views.login, name='login'),
   
re_path(r'^user/(?P<pk>\d+)/profile/$', views.profile, name='profile'),
   
re_path(r'^user/(?P<pk>\d+)/profile/update/$', views.profile_update, name='profile_update'),
   
re_path(r'^user/(?P<pk>\d+)/pwd_change/$', views.pwd_change, name='pwd_change'),
   
re_path(r'^logout/$', views.logout, name='logout'),


第二步 编写视图views.py

from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User
from .models import UserProfile
from django.contrib import auth
from django.conf import settings
from .forms import RegistrationForm, LoginForm, ProfileForm, PwdChangeForm
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.decorators import login_required


@login_required
def logout(request):
   auth.logout(request)
   return HttpResponseRedirect("/accounts/login/")

@login_required
def pwd_change(request, pk):
   user = get_object_or_404(User, pk=pk)

   if request.method == "POST":
       form = PwdChangeForm(request.POST)

       if form.is_valid():

           password = form.cleaned_data['old_password']
           username = user.username

           user = auth.authenticate(username=username, password=password)

           if user is not None and user.is_active:
               new_password = form.cleaned_data['password2']
               user.set_password(new_password)
               user.save()
               return HttpResponseRedirect("/accounts/login/")

           else:
               return render(request, 'users/pwd_change.html', {'form': form,
      
'user': user, 'message': 'Old password is wrong. Try again'})
   else:
       form = PwdChangeForm()

   return render(request, 'users/pwd_change.html', {'form': form, 'user': user})

views.logout非常好理解。我们重点看下views.pwd_change函数是怎么工作的:


  • 首先我们用@login_required装饰器确定用户是否已经登录,只有登录的才能修改个人密码。后面我们会专文介绍装饰器的用法。

  • 我们先从url获取user的主键pk(id), 利用get_object_or_404方法获取需要修改密码的用户对象user

  • 当用户通过POST方法提交密码修改表单,我们先验证表单PwdChangeForm的数据是否有效。如果老的密码是正确的,我们将更新过的密码通过set_password方法数据存入user。修改密码成功后返回登录页面。

  • 如果用户没有提交表单或不是通过POST方法提交表单,我们生成一张空的PwdChangForm


PwdChangeForm包括了老密码,新密码和密码确认3个字段。我们通过form类自带的clean方法在表单里添加了表单验证。要对form里哪个字段进行验证,你自需要定义一个clean_字段名方法。在这个案例里我们需要新密码满足一定长度要求,同时还要求用户两次输入密码是一致的。

# users/forms.py
class PwdChangeForm(forms.Form):

   old_password = forms.CharField(label='Old password', widget=forms.PasswordInput)

   password1 = forms.CharField(label='New Password', widget=forms.PasswordInput)
   password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)

   # Use clean methods to define custom validation rules

   
def clean_password1(self):
       password1 = self.cleaned_data.get('password1')

       if len(password1) < 6:
           raise forms.ValidationError("Your password is too short.")
       elif len(password1) > 20:
           raise forms.ValidationError("Your password is too long.")

       return password1

   def clean_password2(self):
       password1 = self.cleaned_data.get('password1')
       password2 = self.cleaned_data.get('password2')

       if password1 and password2 and password1 != password2:
           raise forms.ValidationError("Password mismatch. Please enter again.")

       return password2


第三步 编写template


#users/templates/users/pwd_change.html

{% block content %}
<h2>Change Password</h2>
{% if message %}
{{ message }}
{% endif %}
<div class="form-wrapper">
  <form
method="post" action="" enctype="multipart/form-data">
     
{% csrf_token %}
     {% for field in form %}
          <div class="fieldWrapper">
       
{{ field.errors }}
       {{ field.label_tag }} {{ field }}
       {% if field.help_text %}
            <p class="help">{{ field.help_text|safe }}</p>
       
{% endif %}
          </div>
       
{% endfor %}
     <div class="button-wrapper submit">
        <input
type="submit" value="Submit" />
     </div>
  </form>
   <a
href="/accounts/logout/">Logout</a>
</div>
{% endblock %}


第四步 查看实战效果


本文介绍了如何利用Django 2.0实现用户密码重置和退出登录的方法。整个用户注册和登录还是太简单了,比如没有邮箱验证,也不能通过第三方APP授权登录,界面也比较丑陋。一个更好的方式是使用已经成熟的第三方Django Package比如django-allauth来实现用户注册和登录。我们后续会专文介绍django-allauth的使用,欢迎关注。



猜你喜欢

转载自blog.csdn.net/weixin_42134789/article/details/80278377