Django完整入门指南-第4部分-2注册

注册

注册

让我们从创建注册视图开始。 首先,在urls.py文件中创建一个新路由:

myproject / urls.py

 from django.conf.urls import url from django.contrib import admin from accounts import views as accounts_views from boards import views urlpatterns = [ url ( r'^$' , views . home , name = 'home' ), url ( r'^signup/$' , accounts_views . signup , name = 'signup' ), url ( r'^boards/(?P<pk> \ d+)/$' , views . board_topics , name = 'board_topics' ), url ( r'^boards/(?P<pk> \ d+)/new/$' , views . new_topic , name = 'new_topic' ), url ( r'^admin/' , admin . site . urls ), ] 

请注意,我们如何以不同的方式从帐户应用程序导入视图模块:

 from accounts import views as accounts_views 

我们使用别名是因为否则会与董事会的观点冲突。 稍后我们可以改进urls.py设计。 但是现在,让我们集中讨论身份验证功能。

现在,在帐户应用程序中编辑views.py并创建一个名为signup的新视图:

account / views.py

 from django.shortcuts import render def signup ( request ): return render ( request , 'signup.html' ) 

创建新模板,名为signup.html :

templates / signup.html

 {% extends 'base.html' %} {% block content %} <h2> Sign up </h2> {% endblock %} 

在浏览器中打开URL http://127.0.0.1:8000/signup/ ,检查是否一切正常:

注册

是时候编写一些测试了:

account / tests.py

 from django.core.urlresolvers import reverse from django.urls import resolve from django.test import TestCase from .views import signup class SignUpTests ( TestCase ): def test_signup_status_code ( self ): url = reverse ( 'signup' ) response = self . client . get ( url ) self . assertEquals ( response . status_code , 200 ) def test_signup_url_resolves_signup_view ( self ): view = resolve ( '/signup/' ) self . assertEquals ( view . func , signup ) 

测试状态代码(200 =成功),以及URL / signup /是否返回正确的视图功能。

 python manage.py test 
 Creating test database for alias 'default'... System check identified no issues (0 silenced). .................. ---------------------------------------------------------------------- Ran 18 tests in 0.652s OK Destroying test database for alias 'default'... 

对于身份验证视图(注册,登录,密码重置等),我们将不使用顶部栏或面包屑。 我们仍然可以使用base.html模板。 它只需要一些调整:

templates / base.html

 {% load static %}<!DOCTYPE html> <html> <head> <meta charset= "utf-8" > <title> {% block title %} Django Boards {% endblock %} </title> <link href= "https://fonts.googleapis.com/css?family=Peralta" rel= "stylesheet" > <link rel= "stylesheet" href= " {% static 'css/bootstrap.min.css' %} " > <link rel= "stylesheet" href= " {% static 'css/app.css' %} " > {% block stylesheet %}{% endblock %} <!-- HERE --> </head> <body> {% block body %} <!-- HERE --> <nav class= "navbar navbar-expand-lg navbar-dark bg-dark" > <div class= "container" > <a class= "navbar-brand" href= " {% url 'home' %} " > Django Boards </a> </div> </nav> <div class= "container" > <ol class= "breadcrumb my-4" > {% block breadcrumb %} {% endblock %} </ol> {% block content %} {% endblock %} </div> {% endblock body %} <!-- AND HERE --> </body> </html> 

我用注释标记了base.html模板中的新位。 区块{ % block stylesheet % }{ % endblock % }{ % block stylesheet % }{ % endblock % } { % block stylesheet % }{ % endblock % }将用于添加特定于某些页面的额外CSS。

区块{ % block body % } { % block body % } { % block body % }包装了整个HTML文档。 我们可以利用它来利用base.html的头来创建一个空文档。 注意我们如何命名结尾块{ % endblock body % } { % endblock body % } { % endblock body % } 。 在这种情况下,为结束标记命名是一种好习惯,因此更容易识别结束位置。

现在使用signup.html模板,而不要使用{ % block content % } { % block content % } { % block content % } ,我们可以使用{ % block body % } { % block body % } { % block body % } 。

templates / signup.html

 {% extends 'base.html' %} {% block body %} <h2> Sign up </h2> {% endblock %} 

注册

太空了

是时候创建注册表单了。 Django有一个名为UserCreationForm的内置表单。 让我们使用它:

account / views.py

 from django.contrib.auth.forms import UserCreationForm from django.shortcuts import render def signup ( request ): form = UserCreationForm () return render ( request , 'signup.html' , { 'form' : form }) 

templates / signup.html

 {% extends 'base.html' %} {% block body %} <div class= "container" > <h2> Sign up </h2> <form method= "post" novalidate > {% csrf_token %} {{ form.as_p }} <button type= "submit" class= "btn btn-primary" > Create an account </button> </form> </div> {% endblock %} 

注册

看起来有点乱,对吗? 我们可以使用form.html模板使它看起来更好:

templates / signup.html

 {% extends 'base.html' %} {% block body %} <div class= "container" > <h2> Sign up </h2> <form method= "post" novalidate > {% csrf_token %} {% include 'includes/form.html' %} <button type= "submit" class= "btn btn-primary" > Create an account </button> </form> </div> {% endblock %} 

注册

嗯,快到了。 当前,我们的form.html部分模板正在显示一些原始HTML。 这是一项安全功能。 默认情况下,Django将所有字符串视为不安全,转义所有可能引起麻烦的特殊字符。 但是在这种情况下,我们可以信任它。

template / includes / form.html

 {% load widget_tweaks %} {% for field in form %} <div class= "form-group" > {{ field.label_tag }} <!-- code suppressed for brevity --> {% if field.help_text %} <small class= "form-text text-muted" > {{ field.help_text | safe }} <!-- new code here --> </small> {% endif %} </div> {% endfor %} 

基本上,在前面的模板中,我们向field.help_text添加了safe选项field.help_text : { { field.help_text|safe } } { { field.help_text|safe } } { { field.help_text|safe } } 。

保存form.html文件,然后再次检查注册页面:

注册

现在,让我们在注册视图中实现业务逻辑:

account / views.py

 from django.contrib.auth import login as auth_login from django.contrib.auth.forms import UserCreationForm from django.shortcuts import render , redirect def signup ( request ): if request . method == 'POST' : form = UserCreationForm ( request . POST ) if form . is_valid (): user = form . save () auth_login ( request , user ) return redirect ( 'home' ) else : form = UserCreationForm () return render ( request , 'signup.html' , { 'form' : form }) 

基本表单处理,其中包含少量细节: 登录功能(重命名为auth_login,以避免与内置登录视图冲突)。

 注意:我将login功能重命名为auth_login ,但后来我意识到Django 1.11为登录视图LoginView提供了一个基于类的视图,因此没有冲突名称的风险。

在较旧的版本上,存在auth.loginauth.view.login ,这常常引起一些混乱,因为一个是登录用户的功能,另一个是视图。

长话短说:您可以根据需要将其作为login导入,这不会造成任何问题。

如果表单有效,则使用user = form.save()创建一个User实例。 然后将创建的用户作为参数传递给auth_login函数,以手动验证用户。 之后,该视图会将用户重定向到主页,从而保持应用程序的流程。

让我们尝试一下。 首先,提交一些无效数据。 空表单,不匹配的字段或现有的用户名:

注册

现在填写表格并提交,检查用户是否已创建并重定向到主页:

注册

在模板中引用经过身份验证的用户

我们怎么知道它是否有效? 好吧,我们可以编辑base.html模板以在顶部栏中添加用户名称:

templates / base.html

 {% block body %} <nav class= "navbar navbar-expand-sm navbar-dark bg-dark" > <div class= "container" > <a class= "navbar-brand" href= " {% url 'home' %} " > Django Boards </a> <button class= "navbar-toggler" type= "button" data-toggle= "collapse" data-target= "#mainMenu" aria-controls= "mainMenu" aria-expanded= "false" aria-label= "Toggle navigation" > <span class= "navbar-toggler-icon" ></span> </button> <div class= "collapse navbar-collapse" id= "mainMenu" > <ul class= "navbar-nav ml-auto" > <li class= "nav-item" > <a class= "nav-link" href= "#" > {{ user.username }} </a> </li> </ul> </div> </div> </nav> <div class= "container" > <ol class= "breadcrumb my-4" > {% block breadcrumb %} {% endblock %} </ol> {% block content %} {% endblock %} </div> {% endblock body %} 

注册

测试注册视图

现在让我们改进测试用例:

account / tests.py

 from django.contrib.auth.forms import UserCreationForm from django.core.urlresolvers import reverse from django.urls import resolve from django.test import TestCase from .views import signup class SignUpTests ( TestCase ): def setUp ( self ): url = reverse ( 'signup' ) self . response = self . client . get ( url ) def test_signup_status_code ( self ): self . assertEquals ( self . response . status_code , 200 ) def test_signup_url_resolves_signup_view ( self ): view = resolve ( '/signup/' ) self . assertEquals ( view . func , signup ) def test_csrf ( self ): self . assertContains ( self . response , 'csrfmiddlewaretoken' ) def test_contains_form ( self ): form = self . response . context . get ( 'form' ) self . assertIsInstance ( form , UserCreationForm ) 

我们对SignUpTests类进行了一些更改。 定义了一个setUp方法,将响应对象移到了那里。 然后,我们现在还要测试响应中是否包含表单和CSRF令牌。

现在,我们将测试成功注册。 这次,让我们创建一个新类来更好地组织测试:

account / tests.py

 from django.contrib.auth.models import User from django.contrib.auth.forms import UserCreationForm from django.core.urlresolvers import reverse from django.urls import resolve from django.test import TestCase from .views import signup class SignUpTests ( TestCase ): # code suppressed... class SuccessfulSignUpTests ( TestCase ): def setUp ( self ): url = reverse ( 'signup' ) data = { 'username' : 'john' , 'password1' : 'abcdef123456' , 'password2' : 'abcdef123456' } self . response = self . client . post ( url , data ) self . home_url = reverse ( 'home' ) def test_redirection ( self ): ''' A valid form submission should redirect the user to the home page ''' self . assertRedirects ( self . response , self . home_url ) def test_user_creation ( self ): self . assertTrue ( User . objects . exists ()) def test_user_authentication ( self ): ''' Create a new request to an arbitrary page. The resulting response should now have a `user` to its context, after a successful sign up. ''' response = self . client . get ( self . home_url ) user = response . context . get ( 'user' ) self . assertTrue ( user . is_authenticated ) 

运行测试。

使用类似的策略,现在让我们创建一个新类,用于在数据无效时进行注册测试:

 from django.contrib.auth.models import User from django.contrib.auth.forms import UserCreationForm from django.core.urlresolvers import reverse from django.urls import resolve from django.test import TestCase from .views import signup class SignUpTests ( TestCase ): # code suppressed... class SuccessfulSignUpTests ( TestCase ): # code suppressed... class InvalidSignUpTests ( TestCase ): def setUp ( self ): url = reverse ( 'signup' ) self . response = self . client . post ( url , {}) # submit an empty dictionary def test_signup_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_dont_create_user ( self ): self . assertFalse ( User . objects . exists ()) 

将电子邮件字段添加到表单

一切正常,但是… 电子邮件地址字段丢失。 很好, UserCreationForm不提供电子邮件字段。 但是我们可以扩展它。

帐户文件夹中创建一个名为forms.py的文件:

account / forms.py

 from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User class SignUpForm ( UserCreationForm ): email = forms . CharField ( max_length = 254 , required = True , widget = forms . EmailInput ()) class Meta : model = User fields = ( 'username' , 'email' , 'password1' , 'password2' ) 

现在,让我们导入新表单SignUpForm ,而不是在views.py中使用UserCreationForm :

account / views.py

 from django.contrib.auth import login as auth_login from django.shortcuts import render , redirect from .forms import SignUpForm def signup ( request ): if request . method == 'POST' : form = SignUpForm ( request . POST ) if form . is_valid (): user = form . save () auth_login ( request , user ) return redirect ( 'home' ) else : form = SignUpForm () return render ( request , 'signup.html' , { 'form' : form }) 

有了这个小小的改动,一切都已经开始了:

注册

请记住,将测试用例更改为使用SignUpForm而不是UserCreationForm :

 from .forms import SignUpForm class SignUpTests ( TestCase ): # ... def test_contains_form ( self ): form = self . response . context . get ( 'form' ) self . assertIsInstance ( form , SignUpForm ) class SuccessfulSignUpTests ( TestCase ): def setUp ( self ): url = reverse ( 'signup' ) data = { 'username' : 'john' , 'email' : 'john@doe.com' , 'password1' : 'abcdef123456' , 'password2' : 'abcdef123456' } self . response = self . client . post ( url , data ) self . home_url = reverse ( 'home' ) # ... 

由于SignUpForm扩展了UserCreationForm , 因此它是 UserCreationForm的一个实例, 因此先前的测试用例仍会通过。

现在让我们考虑一下发生了什么。 我们添加了一个新的表单字段:

 fields = ( 'username' , 'email' , 'password1' , 'password2' ) 

它会自动反映在HTML模板中。 很好吧? 好吧,要看情况。 如果将来有新的开发人员想要将SignUpForm再次用于其他用途,并向其中添加一些额外的字段,该怎么办 ? 然后,这些新字段也将显示在signup.html中 ,这可能不是所需的行为。 这种变化可能会被忽略,我们不希望有任何意外。

因此,让我们创建一个新的测试,以验证模板中的HTML输入:

account / tests.py

 class SignUpTests ( TestCase ): # ... def test_form_inputs ( self ): ''' The view must contain five inputs: csrf, username, email, password1, password2 ''' self . assertContains ( self . response , '<input' , 5 ) self . assertContains ( self . response , 'type="text"' , 1 ) self . assertContains ( self . response , 'type="email"' , 1 ) self . assertContains ( self . response , 'type="password"' , 2 ) 

改善测试布局

好了,因此我们正在测试输入和所有内容,但是我们仍然必须测试表单本身。 我们不仅仅将测试添加到accounts / tests.py文件中,还需要对项目设计进行一些改进。

帐户文件夹中创建一个名为tests的新文件夹。 然后,在tests文件夹内,创建一个名为__init__.py的空文件。

现在,将tests.py文件移动到tests文件夹内,并将其重命名为test_view_signup.py 。

最终结果应为:

 myproject/ |-- myproject/ | |-- accounts/ | | |-- migrations/ | | |-- tests/ | | | |-- __init__.py | | | +-- test_view_signup.py | | |-- __init__.py | | |-- admin.py | | |-- apps.py | | |-- models.py | | +-- views.py | |-- boards/ | |-- myproject/ | |-- static/ | |-- templates/ | |-- db.sqlite3 | +-- manage.py +-- venv/ 

请注意,由于我们在应用程序上下文中使用相对导入,因此我们需要在新的test_view_signup.py中修复导入:

帐户/测试/test_view_signup.py

 from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.urls import resolve from django.test import TestCase from ..views import signup from ..forms import SignUpForm 

我们在应用程序模块内部使用了相对导入,因此以后我们可以自由地重命名Django应用程序,而不必修复所有绝对导入。

现在让我们创建一个新的测试文件,以测试SignUpForm 。 添加一个名为test_form_signup.py的新测试文件:

帐户/测试/test_form_signup.py

 from django.test import TestCase from ..forms import SignUpForm class SignUpFormTest ( TestCase ): def test_form_has_fields ( self ): form = SignUpForm () expected = [ 'username' , 'email' , 'password1' , 'password2' ,] actual = list ( form . fields ) self . assertSequenceEqual ( expected , actual ) 

看起来很严格吧? 例如,如果将来我们必须更改SignUpForm ,以包括用户的名字和姓氏,那么即使我们没有破坏任何内容,我们也可能最终不得不修复一些测试用例。

测试案例警报

这些警报很有用,因为它们有助于提高知名度,特别是对于初次接触该代码的新手。 它帮助他们放心地编写代码。

改进注册模板

让我们做一点工作。 在这里,我们可以使用Bootstrap 4卡组件使其看起来不错。

转到https://www.toptal.com/designers/subtlepatterns/并找到一个很好的背景图案用作帐户页面的背景。 下载它,在静态文件夹中创建一个名为img的新文件夹,然后将图像放在此处。

然后,在static / css中创建一个名为account.css的新CSS文件。 结果应为以下内容:

 myproject/ |-- myproject/ | |-- accounts/ | |-- boards/ | |-- myproject/ | |-- static/ | | |-- css/ | | | |-- accounts.css <-- here | | | |-- app.css | | | +-- bootstrap.min.css | | +-- img/ | | | +-- shattered.png <-- here ( the name may be different, depending on the patter you downloaded ) | |-- templates/ | |-- db.sqlite3 | +-- manage.py +-- venv/ 

现在编辑accounts.css文件:

static / css / accounts.css

 body { background-image : url(../img/shattered.png) ; } .logo { font-family : 'Peralta' , cursive ; } .logo a { color : rgba ( 0 , 0 , 0 , .9 ); } .logo a :hover , .logo a :active { text-decoration : none ; } 

signup.html模板中,我们可以对其进行更改以使用新的CSS,还可以使用Bootstrap 4卡组件:

templates / signup.html

 {% extends 'base.html' %} {% load static %} {% block stylesheet %} <link rel= "stylesheet" href= " {% static 'css/accounts.css' %} " > {% endblock %} {% block body %} <div class= "container" > <h1 class= "text-center logo my-4" > <a href= " {% url 'home' %} " > Django Boards </a> </h1> <div class= "row justify-content-center" > <div class= "col-lg-8 col-md-10 col-sm-12" > <div class= "card" > <div class= "card-body" > <h3 class= "card-title" > Sign up </h3> <form method= "post" novalidate > {% csrf_token %} {% include 'includes/form.html' %} <button type= "submit" class= "btn btn-primary btn-block" > Create an account </button> </form> </div> <div class= "card-footer text-muted text-center" > Already have an account? <a href= "#" > Log in </a> </div> </div> </div> </div> </div> {% endblock %} 

这样,这应该是我们现在的注册页面:

注册


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值