三、Django2.1 搭建多用户的博客网站——登录

0.905字数 1292阅读 2760

目录:Django 2.1 从零开始搭建博客网站系列

服务器环境搭建(选学)

小试牛刀——简单的博客网站

庖丁解牛——多用户的博客网站之用户模块

庖丁解牛——多用户的博客网站之文章模块

华丽转身——多用户的博客网站之扩展功能

项目源码下载:https://github.com/jt1024/lehehe

正文:

对于一个多用户的博客系统,管理员可以从后台直接登录,比如前文中的admin,拥有所有权限;非管理员用户最好是从前台登录,只拥有部分权限。
本文我们将实现这个非管理员用户的管理后台。

1、创建应用

python manage.py startapp account

修改 ./lehehe/settings.py 中的 INSTALLED_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    'account',  # 新增
]

修改 ./lehehe/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('account/', include('account.urls')),  # 新增
]

2、简单的登录

2.1 创建登录表单

新建 ./account/forms.py

from django import forms


class LoginForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField(widget=forms.PasswordInput)

forms是什么?下面我们用 shell 来探索一下,执行下面代码进入 shell 模式

python manage.py shell 

进入shell模式后再控制台执行下列代码

from account.forms import LoginForm
login_form = LoginForm()
print(login_form)

此时会输出:

<tr><th><label for="id_username">Username:</label></th><td><input type="text" name="username" required id="id_username"></td></tr>
<tr><th><label for="id_password">Password:</label></th><td><input type="password" name="password" required id="id_password"></td></tr>

由此可见,LoginForm其实就是登录表单的HTML代码

2.2 登录函数

编辑 ./account/views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from .forms import LoginForm


def user_login(request):
    if request.method == "POST":
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            cd = login_form.cleaned_data
            user = authenticate(username=cd['username'], password=cd['password'])
            if user:
                login(request, user)
                return HttpResponse("Welcome You. You have been authenticated successfully")
            else:
                return HttpResponse("Sorry. Your username or password is not right.")
        else:
            return HttpResponse("Invalid login")

    if request.method == "GET":
        login_form = LoginForm()
        return render(request, "account/login.html", {"form": login_form})
  • login_form.is_valid 在创建实例时,如果传递给表单的数据是符合表单类属性要求的,则返回True,否则返回False
  • login_form.cleaned_data 以字典的形式返回实例的具体数据。如果传入的某项数据不合法,则在cleaned_data的结果中不予显示。

2.3 登录模板

新建 .templates/account/login.html

{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<div class="row text-center vertical-middle-sm">
    <h1>Login</h1>
    <p>Input your username and password</p>
    <form class="form-horizontal" action="." method="post">
        {% csrf_token %} <!--post提交数据时必须要加-->
        {{ form.as_p }} <!--将表单的每个输入框包裹在一个<p>标签内 tags-->
        <input type="submit" value="Login">
    </form>
</div>
{% endblock %}

{% csrf_token %} :使用POST的方法时,必须添加{% csrf_token %}标签,用于处理csrf安全机制

  • {{ form.as_p }} :将表单的每个输入框包裹在一个<p>标签内 tags
  • {{ form.as_table }} :将表单渲染成一个表格元素,每个输入框作为一个<tr>标签
  • {{ form.as_ul }} 将表单渲染成一个列表元素,每个输入框作为一个<li>标签

2.4 配置路由

新建 ./account/urls.py

from django.urls import path
from . import views

app_name = 'account'  # 一定要写这一行,否则html中会报错 'account' is not a registered namespace

urlpatterns = [
    path(r'login/', views.user_login, name='user_login'),
]

2.5 测试

运行Django然后访问 http://127.0.0.1:8000/account/login/

前台登录页面.png

填入 用户名:admin 密码:helloworld


前台登录成功.png

2.6 修改登录模板样式

使用 {{ form.as_p }} 绘制表单,样式太普通,我们自定义表单样式。修改 .templates/account/login.html

{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<div class="row text-center vertical-middle-sm">
    <h1>Login</h1>
    <p>Input your username and password</p>
    <form class="form-horizontal" action="." method="post">
        {% csrf_token %}
        <!--{{ form.as_p }}-->
        <div class="form-group">
            <label for="{{form.username.id_for_label}}" class="col-md-5 control-label" style="color:red">
                <span class="glyphicon glyphicon-user"></span>Username
            </label>
            <div class="col-mid-6 text-left">{{form.username}}</div>
        </div>
        <div class="form-group">
            <label for="{{form.username.id_for_label}}" class="col-md-5 control-label" style="color:blue">
                <span class="glyphicon glyphicon-floppy-open"></span>Password
            </label>
            <div class="col-mid-6 text-left">{{form.password}}</div>
        </div>
        <input type="submit" class="btn btn-primary btn-lg" value="Login">
    </form>
</div>
{% endblock %}

此时再访问 http://127.0.0.1:8000/account/login/ 登录表单的样式已改变

前台登录页面修改样式.png

3、使用Django内置的登录方法

修改 ./account/urls.py

from django.urls import path
from . import views
from django.contrib.auth import views as auth_views

app_name = 'account'  # 一定要写这一行,否则html中会报错 'account' is not a registered namespace

urlpatterns = [
    # path(r'login/', views.user_login, name='user_login'),
    path(r'login/', auth_views.LoginView.as_view(template_name="account/login.html"), name='user_login'),  # 使用Django内置的登录方法
]

在 ./lehehe/settings.py 的最后添加一行代码

LOGIN_REDIRECT_URL = '/blog/'

Django内置的登录方法 LoginView()函数里有一个参数redirect_field_name=LOGIN_REDIRECT_URL,这就是登录后的重定向设置,这行代码就是我们对这个参数的配置,登录后重定向到/blog/

完善通用模板头部,修改 ./templates/header.html

{% load staticfiles %}
<div class="container">
    <nav class="navbar navbar-default" role="navigation">
        <div class="navbar-header">
            <a class="navbar-brand" href="http://www.taoge100.com"><img src="{% static '/images/logo.png' %}" width="100px"></a>
        </div>
        <div>
            <ul class="nav navbar-nav" role="navigation">
                <li><a href="{% url 'blog:blog_list' %}">BLOG</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right" style="margin-right:20px">
                {% if user.is_authenticated %}
                <li><a href="#">{{user.username}}</a></li>
                <li><a href="#">Logout</a></li>
                {% else %}
                <li><a href="{% url 'account:user_login' %}">Login</a></li>
                {% endif %}
            </ul>
        </div>
    </nav>
</div>

4、使用Django内置的登出方法

在 ./account/urls.py 里添加一行代码

path(r'loginout/', auth_views.LogoutView.as_view(template_name="account/logout.html"), name='user_logout'),  # 使用Django内置的登出方法

创建 ./templates/account/logut.html

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

完善通用模板头部,在 ./templates/header.html 中补充 Logout 的超链接

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

5、测试登录、登出效果
登录成功页面

登出页面

推荐阅读更多精彩内容