密码更改视图
该视图供希望更改密码的登录用户使用。通常,这些表格由三个字段组成:旧密码,新密码和新密码确认。
myproject / urls.py (查看完整的文件内容)
url ( r'^settings/password/$' , auth_views . PasswordChangeView . as_view ( template_name = 'password_change.html' ), name = 'password_change' ), url ( r'^settings/password/done/$' , auth_views . PasswordChangeDoneView . as_view ( template_name = 'password_change_done.html' ), name = 'password_change_done' ),这些视图仅适用于登录用户。它们使用名为的视图装饰器@login_required。此装饰器可防止未经授权的用户访问此页面。如果用户未登录,则Django会将其重定向到登录页面。
现在,我们必须在settings.py中定义应用程序的登录URL :
myproject / settings.py (查看完整的文件内容)
LOGIN_URL = 'login'templates / password_change.html
{% extends 'base.html' %} {% block title %} Change password {% endblock %} {% block breadcrumb %} <li class= "breadcrumb-item active" > Change password </li> {% endblock %} {% block content %} <div class= "row" > <div class= "col-lg-6 col-md-8 col-sm-10" > <form method= "post" novalidate > {% csrf_token %} {% include 'includes/form.html' %} <button type= "submit" class= "btn btn-success" > Change password </button> </form> </div> </div> {% endblock %}
templates / password_change_done.html
{% extends 'base.html' %} {% block title %} Change password successful {% endblock %} {% block breadcrumb %} <li class= "breadcrumb-item" ><a href= " {% url 'password_change' %} " > Change password </a></li> <li class= "breadcrumb-item active" > Success </li> {% endblock %} {% block content %} <div class= "alert alert-success" role= "alert" > <strong> Success! </strong> Your password has been changed! </div> <a href= " {% url 'home' %} " class= "btn btn-secondary" > Return to home page </a> {% endblock %}
关于密码更改视图,我们可以实现到目前为止已经执行的类似测试用例。创建一个名为test_view_password_change.py的新测试文件。
我将在下面列出新的测试类型。您可以单击代码段旁边的查看完整文件内容链接,检查我为密码更改视图编写的所有测试。大多数测试与我们到目前为止所做的相似。我移至一个外部文件,以避免过于重复。
account / tests / test_view_password_change.py (查看完整的文件内容)
class LoginRequiredPasswordChangeTests ( TestCase ): def test_redirection ( self ): url = reverse ( 'password_change' ) login_url = reverse ( 'login' ) response = self . client . get ( url ) self . assertRedirects ( response , f '{login_url}?next={url}' )上面的测试尝试在未登录的情况下访问password_change视图。预期的行为是将用户重定向到登录页面。
account / tests / test_view_password_change.py (查看完整的文件内容)
class PasswordChangeTestCase ( TestCase ): def setUp ( self , data = {}): self . user = User . objects . create_user ( username = 'john' , email = 'john@doe.com' , password = 'old_password' ) self . url = reverse ( 'password_change' ) self . client . login ( username = 'john' , password = 'old_password' ) self . response = self . client . post ( self . url , data )在这里,我们定义了一个名为PasswordChangeTestCase的新类。它进行基本设置,创建用户并向password_change视图发出POST请求。在下一组测试用例中,我们将使用此类而不是TestCase类来测试成功的请求和无效的请求:
account / tests / test_view_password_change.py (查看完整的文件内容)
class SuccessfulPasswordChangeTests ( PasswordChangeTestCase ): def setUp ( self ): super () . setUp ({ 'old_password' : 'old_password' , 'new_password1' : 'new_password' , 'new_password2' : 'new_password' , }) def test_redirection ( self ): ''' A valid form submission should redirect the user ''' self . assertRedirects ( self . response , reverse ( 'password_change_done' )) def test_password_changed ( self ): ''' refresh the user instance from database to get the new password hash updated by the change password view. ''' self . user . refresh_from_db () self . assertTrue ( self . user . check_password ( 'new_password' )) def test_user_authentication ( self ): ''' Create a new request to an arbitrary page. The resulting response should now have an `user` to its context, after a successful sign up. ''' response = self . client . get ( reverse ( 'home' )) user = response . context . get ( 'user' ) self . assertTrue ( user . is_authenticated ) class InvalidPasswordChangeTests ( PasswordChangeTestCase ): def test_status_code ( self ): ''' An invalid form submission should return to the same page ''' self . assertEquals ( self . response . status_code , 200 ) def test_form_errors ( self ): form = self . response . context . get ( 'form' ) self . assertTrue ( form . errors ) def test_didnt_change_password ( self ): ''' refresh the user instance from the database to make sure we have the latest data. ''' self . user . refresh_from_db () self . assertTrue ( self . user . check_password ( 'old_password' ))该refresh_from_db()方法确保我们拥有数据的最新状态。它强制Django再次查询数据库以更新数据。我们必须这样做,因为change_password视图会更新数据库中的密码。因此,要测试密码是否确实更改,我们必须从数据库中获取最新数据。
结论
身份验证是大多数Django应用程序非常普遍的用例。在本教程中,我们实现了所有重要的视图:注册,登录,注销,密码重置和更改密码。现在,我们已经有了创建用户并对其进行身份验证的方法,我们将能够继续开发应用程序的其他视图。
关于代码设计,我们仍然需要改进很多事情:templates文件夹开始变得杂乱无章。该板应用的测试仍然杂乱无章。另外,我们必须开始重构新的主题视图,因为现在我们可以检索已登录的用户。我们将很快到达这一部分。
希望您喜欢本教程系列的第四部分!第五部分将于下周,即2017年10月2日发布。如果您希望在第五部分结束时收到通知,则可以订阅我们的邮件列表。
该项目的源代码可在GitHub上获得。项目的当前状态可以在发行标签v0.4-lw下找到。下面的链接将带您到正确的地方:
https://github.com/sibtc/django-beginners-guide/tree/v0.4-lw
←第三部分-高级概念
第5部分-Django ORM→