2.3 用内置方法实现登录和退出

  在Django中,凡是通用的功能,都尽可能提供了默认方法,不需要用户编写代码,只需调用即可实现。

下面学习Django内置的登录方法。在使用之前,要找到这个方法写在什么地方,并且要看看源码。用内置方法实现登录和退出的基本知识如下图所示。

2.3.1 内置的登录方法

  先找到Django的安装位置,我的是在C:\Python35\Lib\site-packages,当然这也放着其他第三方的Python库。

  进入到Django目录中,直接找到写有内置登录函数的文件,即C:\Python35\Lib\site-packages\django\contrib\auth里面的views.py文件。

注意:django1和django2使用的内置函数是不同的

 django使用的内置函数是 auth_views.login

django2 使用的是auth_views.LoginView 

打开./account/urls.py文件,做如下代码编辑。
 1 from django.urls import path
 2 from .import views
 3 from django.contrib.auth import views as auth_views #①
 4 
 5 app_name = 'account'
 6 urlpatterns = [
 7     # path('login/',views.user_login,name='user_login'), #自定义的登录
 8     path('login/',auth_views.LoginView.as_view(template_name='account/login2.html'),name='user_login'), #django内置的登录
 9 
10 ]

   语句①引入了刚才找到的Django内置视图文件,并且将其重新 命名为auth_views,然后在路由配置中,使用auth_view.LoginView调用该视图文件中的LoginView()函数。

  刚才看到的LoginView()函数中规定了模板,即registration/login.html,我们已经将本项目的所有模板都转移到了项目目录中的./templates里面,所以需要在./templates/registration中建立login.html模板。

 1 {% extends "base.html" %}
 2 
 3 {% load staticfiles %}
 4 
 5 {% block title %}Login{% endblock %}
 6 
 7 {% block content %}
 8 <div class="row text-center vertical-middle-sm">
 9     <h1>Login</h1>
10     <p>Input your username and password</p>
11     <form class="form-horizontal" action="{% url 'account:user_login' %}" method="post">{% csrf_token %}
12         <!--{{ form.as_p}}-->
13         <div class="form-group">
14             <label for="{{form.username.id_for_label}}" class="col-md-5 control-label"
15                    style="color:red"><span class="glyphicon glyphicon-user"></span>Username</label>
16             <div class="col-md-6 text-left">{{ form.username }}</div>
17         </div>
18         <div class="form-group">
19             <label for="{{form.password.id_for_label}}" class="col-md-5 control-label"
20                    style="color:blue"><span class="glyphicon glyphicon-floppy-open"></span>Password</label>
21             <div class="col-md-6 text-left">{{ form.password }}</div>
22         </div>
23         <input type="submit" class="btn btn-primary btn-lg" value="Login">
24     </form>
25 </div>
26 {% endblock %}

这次修改的地方是语句②中的action="{% url 'account:user_login' %}",用具体的URL指明了数据的POST目标。

  将Django服务启动,在浏览器的地址栏输入http://127.0.0.1:8000/account/login/

 

要找原因,必须要看一下Django内置的LoginView()函数,在它的参数中有一项redirect_field_name=REDIRECT_FIELD_NAME,这就是登录后重定向的设置,上述跳转的地址,就是这个重定向设置的默认值,要想改变重定向的值,需要在.testsite/settings.py文件中设置LOGIN_REDIRECT_URL的值,在文件中添加此配置(可以放在最后)。

1 LOGIN_REDIRECT_URL = '/blog/'

这行代码的含义是登录后重定向到http://localhost:8000/blog/页面,当然可以设定为任何一个可以访问的地址作为重定向目标地址。

再次登录,发现登录成功之后神奇地转到了指定页面。

前面LoginView()函数设置了默认的模板路径,现在要修改一致,则要编辑./account/urls.py文件,代码如下:

 1 from django.urls import path
 2 from .import views
 3 from django.contrib.auth import views as auth_views
 4 
 5 app_name = 'account'
 6 urlpatterns = [
 7     # path('login/',views.user_login,name='user_login'), #自定义的登录
 8     # path('login/',auth_views.LoginView,name='user_login'),
 9     path('login/',auth_views.LoginView.as_view(template_name='registration/login.html'),name='user_login'), #django内置的登录 #③
10 
11 ]

  为了进行对比,原来的URL不变,新增加一个URL配置语句③,以一个字典类型,向默认的auth_views.LoginViews函数对象传template_name的值,account/login.html就是此前已经写好的登录模板文件。

 保存后访问http://127.0.0.1:8000/account/login/,登录界面展现于眼前。

2.3.2 判断用户是否登录

  在模板中,根据用户是否登录进行不同的显示,修改./templates/header.html模板,使LOGIN所在的位置根据用户登录状态显示不同的内容。如果用户已经登录,则显示用户名和Logout字样;如果用户尚未登录,则显示LOGIN字样,并做超链接到登录界面。

 1 {% load staticfiles %}
 2 <div class="container">
 3     <nav class="navbar navbar-default" role="navigation">
 4         <div class="navbar-header">
 5             <a class="navbar-brand" href="http://www.itdiffer.com"><img src="{%static '/images/logo.png'%}"
 6             width="100px"></a>
 7         </div>
 8         <div>
 9             <ul class="nav navbar-nav" role="navigation">
10                 <li><a href="{% url 'blog:blog_title' %">BLOG</a> </li>
11             </ul>
12             <ul class="nav navbar-nav navbar-right" style="margin-right:10px">
13                 {% if user.is_authenticated %} #①
14                 <li><a href="#">{{ user.username }}</a> </li>
15                 <li><a href="#">Logout</a> </li>
16                 {% else %}
17                 <li><a href="{% url 'account:user_login' %}">LOGIN</a> </li>
18                 {% endif %}
19             </ul>
20         </div>
21     </nav>
22 </div>

  在模板中,语句①类似Python中的if语句,请注意观察这种模板语言的书写规则。在模板中可以通过request.user得到用户对象,user.is_authenticated则是返回用户登录的状态,已经登录返回True,否则返回False。这样在模板中就可以根据用户的状态显示不同的内容。

  上述代码中Logout和用户名的超链接都留空了,后续会填补上。登录之后的导航条状态如下图所示。

  显示了登录用户的用户名和Logout。所谓Logout,即为退出。

2.3.3 内置的退出方法

  Django内置退出函数,与登录函数类似,首先配置URL。

  编辑./account/urls.py文件,增加如下内容。

1 path('logout/',auth_views.LogoutView.as_view(template_name='registration/logged_out.html'),name='user_logout'),

 

  此处配置好后,把./templates/header.html文件中针对Logout的超链接修改一下

1 <li><a href="{% url 'account:user_logout' %}">Logout</a> </li>

检查Django服务是否在运行,刷新页面。如果没有登录,则找一个用户名来登录。一切准备就绪,单击Logout按钮,该用户退出,并且打开如下图所示的页面。

这个页面是Django为退出函数定义好的界面,虽然很丑,但毕竟实现了退出。

的确是丑了点,因为使用的是./templates/registration/logged_out.html默认模板,可以重写这个模板文件,在./templates/account/中创建一个退出的模板文件,名为logout.html,代码如下:

 1 {% extends "base.html" %}
 2 
 3 {% block title %}Logout{% endblock %}
 4 
 5 {% block content %}
 6 <div class="row text-center vertical-middle-sm">
 7     <p>You have log out.</p>
 8     <p>You can <a href="{% url 'account:user_login' %}">login</a> again</p>
 9 </div>
10 {% endblock %}

修改./account/urls.py文件,如下

1 path('logout/',auth_views.LogoutView.as_view(template_name='account/logout.html'),name='user_logout'),

再从登录状态执行退出操作,效果如下图所示。

2.3.4 知识点

1、HttpRequest对象

  当客户端向服务器发送请求时,Django会创建一个包含请求数据的HttpRequest对象,并以参数request传给视图函数,即参数request所引用的对象就是HttpRequest对象。HttpRequest对象有很多属性,下面列出几项(除session外的其他属性都应该被看做是只读的,并且下列各项属性区分大小写)

  • path:返回一个字符串,表示请求页面的路径(不包括域名),例如“/blog/admin”。
  • GET:返回类字典对象,包括所有的HTTP GET参数。
  • POST:返回类字典对象,包括所有的HTTP POST参数。注意,不包括上传文件信息。
  • REQUEST:返回类字典对象,包括所有POST和GET数据(先POST,后GET;在项目实践中,不推荐使用这个属性获得对象数据,使用GET、POST更清晰)
  • FILES:返回类字典对象,包含所有的上传文件,每个键是<input type="file" name=""/>中name的值,每个值是一个python字典,该字典有以下三个键:①filename,上传文件的文件名;②content-type,上传文件的内容类型;③content,上传文件的原始内容。注意FILES只有在请求方式为POST并且表单包括enctype="multipart/ form-data"属性时才会有数据,否则FILES就是一个空的类似字典的对象。
  • COOKIES:返回字典,包括所有的cookie键值对。
  • META:返回字典,包含所有可能的HTTP头。
  • user:返回django.contrib.auth.users.User对象,表示当前登录用户。如果当前没有用户登录,user被设置成django.contrib.auth.models.AnonymousUser的一个实例,可以用is_anonymous()来区分登录用户和未登录用户,例如,
    if request.user.is_anonymous():
        # Do something for anonymous users.
    else:
        # Do something for logged-in users.

    ·

  • session:返回可读写的类字典对象,表示当前的session。

在一个HttpRequest对象中,GET和POST属性都是django.http.QueryDict的实例。QueryDict是一个类字典的对象,可以处理同一个键有多个值的情况。

2、HttpResponse对象

HttpResponse是视图向客户端返回的对象。典型的用法就是将页面的内容作为字符串传递给HttpResponse函数,例如(以下示例来自官方文档):

 

 

posted @ 2019-04-09 17:07  taoziya  阅读(188)  评论(0)    收藏  举报