zoukankan      html  css  js  c++  java
  • Django之博客系统:用户登陆

    使用django有一个好处就是有各种各样的框架可以拿来直接使用。相比flaskdjango自带的框架确实要多很多。比如这一章就要介绍的用户登录。Django拥有一个内置的认证(authentication)框架用来操作用户认证(authentication),会话(sessions),权限(permissions)以及用户组。这个认证(authentication)系统包含了一些普通用户的操作视图(views),例如:登录,登出,修改密码以及重置密码

    这个认证(authentication)框架位于django.contrib.auth,被其他Djangocontrib包调用,我们在之前的blog引用中使用这个认证(authentication)框架并为blog创建了一个超级用户来管理站点。

    我们在创建应用的时候,认证框架已经包含了,在settings.py中的MIDDLEWARE

    MIDDLEWARE = [

        'django.middleware.security.SecurityMiddleware',

        'django.contrib.sessions.middleware.SessionMiddleware',

        'django.middleware.locale.LocaleMiddleware',

        'django.middleware.common.CommonMiddleware',

        'django.middleware.csrf.CsrfViewMiddleware',

        'django.contrib.auth.middleware.AuthenticationMiddleware',

        'django.contrib.messages.middleware.MessageMiddleware',

        'django.middleware.clickjacking.XFrameOptionsMiddleware',

    ]

    AuthenticationMiddleware:使用会话(sessions)将用户和请求(requests)进行关联

    SessionMiddleware:通过请求(requests)操作当前会话(sessions

    这个认证(authentication)系统还包含了以下模型(models):

    User:一个包含了基础字段的用户模型(model);这个模型(model)的主要字段有:username, password, email, first_name, last_name, is_active

    Group:一个组模型(model)用来分类用户

    Permission:执行特定操作的标识

    下面我们就要来创建一个登录的视图。通过执行以下的操作来登录用户

    通过提交的表单获取usernamepassword

    将得到的用户名和密码和存储在数据库中的进行认证

    检查用户是否存在

    登录用户到网站并且开始一个认证和会话

    首先创建一个登录表单,在form.py中添加如下代码:

    class LoginForm(forms.Form):

        username=forms.CharField()

    password=forms.CharField(widget=forms.PasswordInput)

    forms.PasswordInput是在密码输入的HTML界面进行渲染的。接着在views.py中添加登录处理的代码

    def user_login(request):

        if request.method == 'POST':

            form=LoginForm(request.POST)

            if form.is_valid():

                cd=form.cleaned_data

                user=authenticate(username=cd['username'],password=cd['password'])

                if user is not None:

                    if user.is_active:

                        login(request,user)

                        return HttpResponse(u'登录成功')

                    else:

                        return HttpResponse(u'登录失败')

                else:

                    return HttpResponse(u'非法登录,请注册用户')

        else:

            form=LoginForm()

    return render(request,'blog/login.html',{'form':form})

    通过使用form=LoginForm(request.POST)得到提交的实例化表单

    2 form.is_valid()检查这个表单是否正确,如果正确,通过form.cleaned_data

    取出登录的用户名和密码

    如果用户是有效的,通过user=authenticate(username=cd['username'],password=cd['password'])

    对获取到的用户名和密码进行认证

    如果用户可用,则用login(request,user)方法集合用户到会话中然后返回一条成功的消息

    接下来就是创建url了。在mysiteurls.py中添加url(r'^account/',include('blog.urls')),

    urlpatterns = [

        url(r'^admin/', admin.site.urls),

        url(r'^blog/',include('blog.urls',namespace='blog',app_name='blog')),

        url(r'^test/$',views.test),

        url(r'^account/',include('blog.urls')),

    ]

    blog应用下的urls.py中添加url(r'^login/$',views.user_login)

    urlpatterns = [

        # post views

        url(r'^$', views.post_list_page, name='post_list'),

        url(r'^(?P<post_id>d+)/share/$',views.post_share,name='post_share'),

        url(r'^(?P<post_id>d+)/comment/$',views.post_comment,name='post_comment'),

        url(r'^test/$',views.test),

        url(r'^login/$',views.user_login)

    ]

    最后来看我们的登录模板,在templates/blog下新建一个login.html

    {% extends "base.html" %}

    {% block title %}登录{% endblock %}

    {% block content %}

        <h1>用户登录</h1>

        <p>请输入用户名和密码:</p>

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

            {{ form.as_p }}

            {% csrf_token %}

            <p><input type="submit" value="Log-in"></p>

        </form>

    {% endblock %}

    现在视图,url,模板都已经具备了,下面我们就是要创建一个真实的用户了。运行服务器进入admin界面进行用户名注册:用超级用户名进入后在Users点击add

    输入用户名和帐号

    权限设置

    这里注意一点,如果忘记了普通用户的用户名和密码,可以登录超级用户帐号进去修改,但是如果连超级用户的密码也忘记了,可以通过如下的方式来修改:

    pycharm中进入Python console

    输入如下代码操作用户数据库:

    from django.contrib.auth.models import User

    user=User.objects.get(username='用户名')

    user.set_password('密码‘)

    user.save()

    下面我们就来开始登录,在浏览器中输入:http://127.0.0.1:8000/account/login/

    得到如下的界面

    输入用户名和密码后提示登录成功。

    django还提供以下视图(views)来处理认证(authentication):

    • login:操作表单(form)中的登录然后登录一个用户
    • logout:登出一个用户
    • logout_then_login:登出一个用户然后重定向这个用户到登录页面

    Django提供以下视图(views)来操作密码修改:

    • password_change:操作一个表单(form)来修改用户密码
    • password_change_done:当用户成功修改他的密码后提供一个成功提示页面

    Django还包含了以下视图(views)允许用户重置他们的密码:

    • password_reset:允许用户重置他的密码。它会生成一条带有一个token的一次性使用链接然后发送到用户的邮箱中。
    • password_reset_done:告知用户已经发送了一封可以用来重置密码的邮件到他的邮箱中。
    • password_reset_complete:当用户重置完成他的密码后提供一个成功提示页面。

    blog应用中的urls.py中添加如下代码:

    from django.contrib.auth.views import login

    from django.contrib.auth.views import logout

    from django.contrib.auth.views import logout_then_login

    from django.contrib.auth.views import password_change

    from django.contrib.auth.views import password_change_done

    from django.contrib.auth.views import password_reset

    from django.contrib.auth.views import password_reset_done

    from django.contrib.auth.views import password_reset_confirm

    from django.contrib.auth.views import password_reset_complete

    然后在urlpatterns中添加对应的路径处理函数

    urlpatterns = [

        # post views

        url(r'^$', views.post_list_page, name='post_list'),

        url(r'^(?P<post_id>d+)/share/$',views.post_share,name='post_share'),

        url(r'^(?P<post_id>d+)/comment/$',views.post_comment,name='post_comment'),

        url(r'^test/$',views.test),

        url(r'^login/$',login),

        url(r'^logout/$', logout, name='logout'),

        url(r'^logout-then-login/$', logout_then_login, name='logout_then_login'),

        url(r'^password-change/$', password_change, name='password_change'),

        url(r'^password-change/done/$', password_change_done, name='password_change_done'),

        url(r'^password-reset/$',

                password_reset,

                name='password_reset'),

        url(r'^password-reset/done/$',

            password_reset_done,

            name='password_reset_done'),

        url(r'^password-reset/confirm/(?P<uidb64>[-w]+)/(?P<token>[-w]+)/$',

            password_reset_confirm,

            name='password_reset_confirm'),

        url(r'^password-reset/complete/$',

            password_reset_complete,

            name='password_reset_complete'),

    ]

    比如输入http://127.0.0.1:8000/account/password-change/则会自动跳转到密码修改的界面:

    那么现在我们来优化下我们的登陆功能,前面在登陆完成以后跳转到一个页面提示跳转成功。现在我们来优化下这个功能,登陆后跳转到登陆前的界面

    首先在url

    我们将url(r'^login/$',views.user_login)替换成url(r'^login/$',login,name="login")

    也就是我们使用django中的登陆认证模块,使用这种认证模块必须在templates目录下创建一个新的目录命名为registration。这个路径是Django认证(authentication)视图(view)期望你的认证(authentication)模块(template)默认的存放路径。如果没有这个路径的话会提示如下的错误:

    在这个新目录中创建一个新的文件,命名为login.html,然后添加如下代码:

    {% extends "blog/base.html" %}

    {% block title %}Log-in{% endblock %}

    {% block content %}

      <h1>用户登录</h1>

      {% if form.errors %}

        <p>

          用户或密码不匹配,请输入正确的用户名和密码.

        </p>

      {% else %}

        <p>填入下面的信息登陆:</p>

      {% endif %}

      <div class="login-form">

        <form action="{% url 'login' %}" method="post">

          {{ form.as_p }}

          {% csrf_token %}

          <input type="hidden" name="next" value="{{ next }}" />

          <p><input type="submit" value="Log-in"></p>

        </form>

      </div>

     {% endblock %}

    我们添加了一个隐藏的HTML<input>元素来提交叫做next的变量值。当你在请求(request)中传递一个next参数(举个例子:http://127.0.0.1:8000/account/login/?next=/account/),这个变量是登录视图(view)首个设置的参数。

    next参数必须是一个URL。当这个参数被给予的时候,Django登录视图(view)将会在用户登录完成后重定向到给予的URL。也就是在登陆完成后URL将从http://127.0.0.1:8000/account/login/?next=/account/跳转到http://127.0.0.1:8000/account

    settings.py中添加如下配置。LOGIN_URLLOGOUT_URL

    from django.core.urlresolvers import reverse_lazy

    LOGIN_URL = reverse_lazy('login')

    LOGOUT_URL = reverse_lazy('logout')

    这些设置的意义:

    LOGIN_URL:重定向用户登录的URL(例如:使用login_required装饰器(decorator))。

    LOGOUT_URL:重定向用户登出的URL

    我们使用reverse_lazy()来通过它们的名字动态构建URLreverse_lazy()方法就像reverse()所做的一样reverses URLs,但是你可以通过使用这种方式在你项目的URL配置被读取之前进行reverse URLs

    我们现在来测试下,在post_list_page中使用login_required进行修饰

    @login_required

    def post_list_page(request):

        object_list = Post.objects.all()

        paginator = Paginator(object_list, 1)  # 3 posts in each page

        page = request.GET.get('page')

    new_comment = None

    注意:这里的使用方式比较灵活。我们也可以在login_required中进行登录跳转界面的设置,这里设置了的话那么在settings.py中就不用设置了LOGIN_URL

    @login_required(login_url='/account/login')

    def post_list_page(request):

        object_list = Post.objects.all()

        paginator = Paginator(object_list, 1)  # 3 posts in each page

        page = request.GET.get('page')

        new_comment = None

    下面我来进行测试,在浏览器中输入http://127.0.0.1:8000/blog。由于没有登录所以自动会跳转到http://127.0.0.1:8000/account/login/?next=/blog/进行用户登陆。这里并且传递了next的参数

    输入用户名和密码后重新回到了http://127.0.0.1:8000/blog的地址并且显示了博客内容

    既然已经实现了登陆,那么下面来看下退出登陆。首先在registration中创建一个logged_out.html。注意这个名称必须是logged_out,否则在退出登录的时候会自动跳转到admin/logout也就是管理页面的登出界面。文件代码如下:

    {% extends "blog/base.html" %}

    {% block title %}Logged out{% endblock %}

    {% block content %}

      <h1>用户退出</h1>

      <p>你已经退出登陆<a href="{% url "login" %}">重新登陆</a></p>

    {% endblock %}

    在我们的博客显示界面添加退出登陆的链接:

    <span class="user">

           {% if request.user.is_authenticated %}

             你好 {{ request.user.first_name }},

             <a href="{% url "logout" %}">退出</a>

           {% endif %}

    </span>

    页面显示如下

    点击退出跳转到退出登陆的界面。我们点击重新登陆

    我们点击重新登陆并再次输入用户名和密码却提示出错:

    原因在于,我们在点重新登陆的时候,页面跳转到http://127.0.0.1:8000/account/login/。请注意,这个URL并没有next参数,也就是说只是纯粹的一个登录界面,在login.html中由于无法获取到next参数的值因此无法回到退出前的界面。此时url变为http://127.0.0.1:8000/accounts/profile/。我们在url中并没有这个路由,因此报错

    那么如何解决呢,方法是在settings.py中设置登陆后的跳转界面

    LOGIN_REDIRECT_URL = reverse_lazy('list')

    并且在应用的urls.py中添加了路由

    url(r'^$',views.post_list_page,name='list'),

    这样在重新登陆后,界面将跳转到list这个url。这样我们再重新登录的时候就不会有问题了

    django的模块中还有修改密码,重置密码等功能,用法都是差不多的。这里简单介绍下

    修改密码:

    registration/目录下添加一个新的文件命名为password_form.html。添加如下代码:

    {% extends "/blog/base.html" %}{% block title %}Change you password{% endblock %}{% block content %}

      <h1>Change you password</h1>

      <p>Use the form below to change your password.</p>

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

        {{ form.as_p }}

        <p><input type="submit" value="Change"></p>

        {% csrf_token %}

      </form>{% endblock %}

    在相同的目录下创建另一个文件,命名为password_change_done.html来显示密码修改成功,为它添加如下代码:

    {% extends "blog/base.html" %}{% block title %}Password changed{% endblock %}{% block content %}

      <h1>Password changed</h1>

      <p>Your password has been successfully changed.</p>

     {% endblock %}

  • 相关阅读:
    JS offset
    CSS 实现大小写切换
    CSS 选择器的优先级
    JS DOM hasChildNodes的用法
    HTML fieldset和legend标签
    JS this的用法
    js基础之DOM中元素对象的属性方法
    php windows环境 安装 Apache-apollo + phpMQTT 实现发送 MQTT
    php 执行exec() 操作linux 命令
    linux office转换pdf
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/8597833.html
Copyright © 2011-2022 走看看