Django做一个简单的博客系统(6)----用户注册登录

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42567323/article/details/102631159
前言

    前面几篇博客完成了文章基本的增删改查:

    接下来就要做下一个子任务------用户登录与注册
    感谢大神的教程:Django搭建个人博客.

一.准备工作

    对于大部分网站来说,用户数据可谓是比较重要的数据了.而用户管理就是对用户数据的增删改查,自然也是十分重要.我们首先从用户登录开始.
    由于用户管理和文章管理的功能不相同,所以我们再创建一个用户管理的app,专门用来做用户管理:

python manager.py startapp userprofile

    然后就把这个app配置好.

二.用户登录

1.处理表单类

    在userprofile下创建一个forms.py文件:

from django import forms
from django.contrib.auth.models import User

# 登录表单
# 这里使用Form而不是ModelForm是因为用户登录不需要与数据库进行交互
class UserLoginForm(forms.Form):
    username = forms.CharField()
    password = forms.CharField()

2.编写视图函数

userprofile/views.py:

from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import authenticate,login,logout
from django.http import HttpResponse
from userprofile.forms import UserLoginForm,UserRegisterForm
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required

def user_login(request):
    if request.method == 'POST':
        user_login_form = UserLoginForm(data=request.POST)
        if user_login_form.is_valid():
            # .cleaned_data 清洗出合法数据
            data = user_login_form.cleaned_data
            # 检验账号、密码是否正确匹配数据库中的某个用户
            # 如果均匹配则返回这个 user 对象
            user = authenticate(username=data['username'], password=data['password'])
            if user:
                # 将用户数据保存在 session 中,即实现了登录动作
                login(request, user)
                return redirect("article:article_list")
            else:
                return HttpResponse("账号或密码输入有误。请重新输入~")
        else:
            return HttpResponse("账号或密码输入不合法")
    elif request.method == 'GET':
        user_login_form = UserLoginForm()
        context = { 'form': user_login_form }
        return render(request, 'userprofile/login.html', context)
    else:
        return HttpResponse("请使用GET或POST请求数据")

    其中:

  • 用户登录跟发表文章的表单类类似.Form对象的任务就是验证数据,调用is_valid()方法验证;
  • user_login_form.cleaned_data就是从用户提交的数据中清洗出合法的数据;
  • authenticate()方法验证用户名称和密码是否匹配,如果是,则将这个用户数据返回;
  • login(request, user)实现用户登录,并将用户数据保存在session中,我们就不用自己再写session了.

3.编写登录模板

/templates/userprofile/login.html:

% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-12">
            <br>
            <form method="post" action=".">
                {% csrf_token %}
                <!-- 账号 -->
                <div class="form-group">
                    <label for="username">账号</label>
                    <input type="text" class="form-control" id="username" name="username">
                </div>
                <!-- 密码 -->
                <div class="form-group">
                    <label for="password">密码</label>
                    <input type="password" class="form-control" id="password" name="password">
                </div>
                <!-- 提交按钮 -->
                <button type="submit" class="btn btn-primary">提交</button>
            </form>
        </div>
    </div>
</div>
{% endblock content %}

    修改一下tempalates/header.html,把登录的按钮加进去:

<ul class="navbar-nav">
    ...

    <li class="nav-item">
        <a class="nav-link" href="{% url 'article:article_list' %}">文章</a>
    </li>

    <!-- Django的 if 模板语句 -->
    {% if user.is_authenticated %}
        <!-- 如果用户已经登录,则显示用户名下拉框 -->
        <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              {{ user.username }}
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a class="dropdown-item" href="#">退出登录</a>
            </div>
        </li>
    <!-- 如果用户未登录,则显示 “登录” -->
    {% else %}
        <li class="nav-item">
            <a class="nav-link" href="{% url 'userprofile:login' %}">登录</a>
        </li>                    
    <!-- if 语句在这里结束 -->
    {% endif %}
</ul>

4.配置url

Personal_Blog/urls.py:

path('userprofile/', include('userprofile.url',namespace='userprofile')),

userprofile/url.py:

path('login/',views.user_login,name='login'),

    然后运行程序就行.

三.用户登出

    有了用户登录,用户登出就简单了:

1.编写视图函数

userprofile/views.py

# 引入logout模块
from django.contrib.auth import authenticate, login, logout

...
# 用户退出
def user_logout(request):
    logout(request)
    return redirect("article:article_list")

2.配置url

userprofile/url.py:

path('logout/',views.user_logout,name='logout'),

3.修改header

header.html:

# 改动 href 中的链接指向
<a class="dropdown-item" href='{% url "userprofile:logout" %}'>退出登录</a>

    然后运行程序就行.

四.用户注册

1.注册表单类

userprofile/forms.py:

# 注册用户表单
class UserRegisterForm(forms.ModelForm):
    # 复写User的密码
    password = forms.CharField()
    password2 = forms.CharField()

    class Meta:
        model = User
        fields = ('username','email')

    # 对两次输入的密码是否一致进行检查
    def clean_password2(self):
        data = self.cleaned_data
        if data.get('password') == data.get('password2'):
            return data.get('password')
        else:
            return forms.ValidationError("两次密码输入不一致")

2.编写视图函数

userprofile/views.py:

# 用户注册
def user_register(request):
    if request.method == "POST":
        user_register_form = UserRegisterForm(data=request.POST)
        if user_register_form.is_valid():
            new_user = user_register_form.save(commit=False)
            new_user.set_password(user_register_form.cleaned_data['password'])
            new_user.save()
            # 保存好数据后立即登录并返回博客列表页面
            login(request, new_user)
            return redirect("article:article_list")
        else:
            return HttpResponse("注册表单输入有误。请重新输入~")
    elif request.method == "GET":
        user_register_form = UserRegisterForm()
        context = {'form': user_register_form}
        return render(request, 'userprofile/register.html', context)
    else:
        return HttpResponse("请使用GET或POST请求数据")

3.编写模板

userprofile/register.html

{% extends "base.html" %} {% load staticfiles %}
{% block title %} 登录 {% endblock title %}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-12">
            <br>
            <form method="post" action=".">
                {% csrf_token %}
                <!-- 账号 -->
                <div class="form-group col-md-4">
                    <label for="username">昵称</label>
                    <input type="text" class="form-control" id="username" name="username" required>
                </div>
                <!-- 邮箱 -->
                <div class="form-group col-md-4">
                    <label for="email">Email</label>
                    <input type="text" class="form-control" id="email" name="email">
                </div>
                <!-- 密码 -->
                <div class="form-group col-md-4">
                    <label for="password">设置密码</label>
                    <input type="password" class="form-control" id="password" name="password" required>
                </div>
                <!-- 确认密码 -->
                <div class="form-group col-md-4">
                    <label for="password2">确认密码</label>
                    <input type="password" class="form-control" id="password2" name="password2" required>
                </div>
                <!-- 提交按钮 -->
                <button type="submit" class="btn btn-primary">提交</button>
            </form>
        </div>
    </div>
</div>
{% endblock content %}

在登录页面中添加:
uerprofile/login.html:

<div class="col-12">
    <br>
    <h5>还没有账号?</h5>
    <h5>点击<a href='{% url "userprofile:register" %}'>注册账号</a>加入我们吧!</h5>
    <br>
    <form method="post" action=".">
        ...
    </form>
</div>

4.配置url

userprofile/url.py:

path('register/',views.user_register,name='register'),

然后运行项目就行.

五.用户删除

    相对于用户登录与注册,用户的删除需要更谨慎.

1.编写视图函数

userprofile/views.py:

# @login_required是一个python装饰器.
# 装饰器可以在不改变某个函数内容的前提下,给这个函数添加一些功能.
# 具体来说,就是@login_required要求调用user_delete()函数时,用户必须登录
# 如果未登录则不执行函数,将页面重定向到'/userprofile/login/'地址去
# 装饰器确认用户已经登录后,允许调用user_delete(),
# 然后需要删除的用户id通过请求传递到视图中,
# 由if语句确认是否与登录的用户一致
# 成功后则退出登录并删除用户数据,返回博客列表页面

@login_required(login_url='/userprofile/login/')
def user_delete(request,id):
    if request.method == "POST":
        user = User.objects.get(id=id)
        # 验证登录用户,待删除用户是否相同
        if request.user == user:
            # 退出登录,删除数据并返回博客列表
            logout(request)
            user.delete()
            return redirect("article:article_list")
        else:
            return HttpResponse('你没有删除操作的权限')
    else:
        return HttpResponse("仅接收post请求")

2.编写模板

改写header.html:

<!-- 定义导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">

    <!-- 导航栏商标 -->
    <a class="navbar-brand" href="#">我的博客</a>

    <!-- 导航入口 -->
    <div>
      <ul class="navbar-nav">
        <!-- 条目 -->
        <li class="nav-item">
        <a class="nav-link" href="{% url 'article:article_create' %}">写文章</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="{% url 'article:article_list' %}">文章</a>
        </li>

        {% if user.is_authenticated %}
        <!-- 如果用户已经登录,则显示用户名下拉框 -->
        <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              {{ user.username }}
            </a>
            <div class="dropdown-menu" aria-labelledby="navbarDropdown">
              <a class="dropdown-item" href="#" onclick="user_delete()">删除用户</a>
              <a class="dropdown-item" href="{% url 'userprofile:logout' %}">退出登录</a>
            </div>
        </li>
    <!-- 如果用户未登录,则显示 “登录” -->
    {% else %}
        <li class="nav-item">
            <a class="nav-link" href="{% url 'userprofile:login' %}">登录</a>
        </li>
    <!-- if 语句在这里结束 -->
    {% endif %}
      </ul>
    </div>

  </div>
</nav>

<!-- 新增 -->
{% if user.is_authenticated %}
<form
    style="display:none;"
    id="user_delete"
    action="{% url 'userprofile:delete' user.id %}"
    method="POST"
>
{% csrf_token %}
    <button type="submit">发送</button>
</form>
    <script>
        function user_delete() {
            // 调用layer弹窗组件
            layer.open({
                title: "确认删除",
                content: "确认删除用户资料吗?",
                yes: function(index, layero) {
                    $('form#user_delete button').click();
                    layer.close(index);
                },
            })
        }
    </script>
{% endif %}

3.配置url

userprofile/url.py:

path('delete/<int:id>',views.user_delete,name='delete'),

然后运行项目就可以了

写在最后

    本文是个人的一些学习笔记,如有侵权,请及时联系我进行删除,谢谢大家.

猜你喜欢

转载自blog.csdn.net/weixin_42567323/article/details/102631159