飞道的博客

Python Web 菜谱项目再次前进一步,从应用层了解内置用户认证系统

392人阅读  评论(0)

橡皮擦,一个逗趣的互联网高级网虫。新的系列,让我们一起进入 Django 世界。

已经完成的文章

九、Django 用户认证与鉴权,注册登录逻辑实现,注销功能

9.1 Django 用户认证

之前的博客中已经对 Django 中用户身份认证系统有过初步了解,在这套用户身份认证系统中可以处理用户账户,用户组,用户权限,Cookie 想干问题,主要解决了 Web 系统中两个问题,分别是认证、鉴权。

认证解决的是否可以登录问题,鉴权解决用户登录之后可以做什么的问题。

在 Django 中内置了一个 User 模型,字段如下:

  • username:用户名,150 字符以内;
  • firstname:名字字段,30 字符以内,国内不常用;
  • lastname:姓字段,150 字符以内,国内不常用;
  • email:邮箱字段;
  • password:密码字段;
  • groups:用户组字段;
  • is_staff:是否是管理员,布尔类型;
  • is_active:用户是否可用,布尔类型;
  • is_superuser:超级管理员字段;
  • last_login:用户最后登录时间;
  • date_joined:用户账号创建时间。

9.1.1 创建用户

在 Django 的用户系统中,因为涉及密码管理,不能直接通过 User 类的构造函数创建 User 对象并调用 save 方法创建用户。
一般使用 User 模型的 Manage 提供的 create_user 方法,传入参数实现对用户的创建。

# 第一个参数是用户名,第二个参数是邮箱,第三个参数是密码
user = User.objects.create_user("xiangpica","xxxxxxxxx@88.com","admin_123")

修改密码,使用下述方法。

user = User.objects.get(username="xiangpica")
user.set_password("C@xiang")
user.save()

这个是普通用户的创建方式,如果希望创建一个超级用户,使用 createsuperuser 命令即可,可参考下述步骤。

> python manage.py createsuperuser
Username (leave blank to use 'administrator'): xiang
Email address: w@163.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

9.2 注册登录逻辑实现

接下来就要实现上文未完成的逻辑部分想干代码了,这里需要补充的知识也比较抽象,第一个就是在一个网站中,如果用户登录成功,Django 会通过 cookie 信息记录用户的登录状态,并且可以通过 cookie 中的信息查找到 session(会话)和用户信息,依旧是先实现,再补充逻辑知识点。

9.2.1 注册用户入库

在正式注册前,先打开 sqlite3 看一下里面的数据,这里橡皮擦使用的软件是 https://sqlitebrowser.org/dl/ 。直接打开项目目录的 db.sqlite3 文件即可查阅。


修改 views.py 文件中内部逻辑,修改 register.html 页面逻辑,代码如下:
views.py

# 投入记住先导入该模块
from django.contrib.auth.models import User
def register(request):
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse("default"))

    # 用户注册状态信息
    state = None
    # 当用户提交注册信息
    if request.method == "POST":
        username = request.POST.get("username", "")
        password = request.POST.get("password", "")
        email = request.POST.get("email", "")
        # 判断用户名是否存在
        if User.objects.filter(username=username):
            state = "user_exist"

        else:
            n_user = User.objects.create_user(username=username, password=password, email=email)
            # 保存注册信息到数据库
            n_user.save()
            state = "success"  # 表示注册成功

    context = {
   
        "active_menu": 'default',
        "user": None,
        "state": state
    }
    return render(request, "menuapp/register.html", context)

register.html

{% block content %}
<div class="container">
  <h2 class="form-signup-heading">注册</h2>
  <div class="well">
    {% if state == "user_exist" %}
    <h2 class="text-warning">用户已经被注册!</h2>
    {% endif %} {% if state == "success" %}
    <h2 class="text-success">注册成功!</h2>
    {% endif %}
  </div>
</div>

重新运行菜谱程序,注册用户,第一次成功,第二次在注册,提示用户已经被注册,此时注册界面完成最小可用功能。

查询数据库数据,发现已经入库。

9.2.2 用户登录完善

模仿注册相关实现,对登录逻辑进行补充,重点修改 views.py 文件与 login.html 文件:

login.html

{% block content %}
<div class="container">
  <h2 class="form-signup-heading">登录</h2>
  {% if state == "login_error" %}
  <h2 class="text-warning">用户名或者密码错误!</h2>
  {% endif %}
</div>

views.py

# 提前导入 auth 模块
from django.contrib import auth
# 登录视图
def login(request):
    if request.user.is_authenticated:
        return HttpResponseRedirect(reverse("default"))
    # 登录状态信息
    state = None
    if request.method == "POST":
        username = request.POST.get("username", "")
        password = request.POST.get("password", "")
        # 登录验证
        user = auth.authenticate(username=username, password=password)
        if user is not None:
            auth.login(request, user)
            return HttpResponseRedirect(reverse("default"))
        else:
            state = "login_error"

    context = {
   
        "active_menu": 'default',
        "user": None,
        "state": state
    }
    return render(request, "menuapp/login.html", context)

修改完毕之后,运行网站,结果出现如下错误,反复查询之后,在 urls.py 文件中,一个路由的名字写错了,修改如下:

from django.urls import path
from . import views

urlpatterns = [
    path("", views.index, name="default"),
    path("register", views.register, name="register"),
    path("login", views.login, name="login")
]

上述代码成功解决下述问题。


以上代码正常运行的结果是,当用户正常登录之后,会跳转到首页,重新去访问登录页面,也会跳转到首页,简单理解就是你的登录页面进不去了,除非手动删除本地 cookie。

9.3 用户注销

注销不需要有页面,但是需要完成 views.py 中的 logout 函数。

def logout(request):
    # 注销登录
    auth.logout(request)
    return HttpResponseRedirect(reverse("default"))

修改完毕 views.py 代码之后,还要在 urls.py 中新增注销用户的路由。

urlpatterns = [
    path("", views.index, name="default"),
    path("register", views.register, name="register"),
    path("login", views.login, name="login"),
    path("logout", views.logout, name="logout")
]

访问 http://127.0.0.1:8000/logout 实现注销,同时 http://127.0.0.1:8000/login 可以再次访问。

9.4 本篇博客小节

本篇博客对菜谱系统的登录与注册页面逻辑进行了补充,实现了基于内置 User 模型的增加操作。文章难度虽然不大,但是核心知识点比较多,并且有许多位置的技术知识点被后置了,这些内容在后续都将为你展开,一起坚持学习吧。

相关阅读

  1. Python 爬虫 100 例教程,超棒的爬虫教程,立即订阅吧
  2. Python 游戏世界(更新中,目标文章数 50+,现在订阅,都是老粉)
  3. Python 爬虫小课,精彩 9 讲

今天是持续写作的第 127 / 200 天。
如果你想跟博主建立亲密关系,可以关注同名公众号 梦想橡皮擦,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家点赞评论收藏

Django 教程 为什么python不适合开发网站 django框架要学多久 django开源项目 django适合前后端分离吗 django 用的人多吗 python web为什么不火 django中文文档 django搭建web服务器
转载:https://blog.csdn.net/hihell/article/details/115455162
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场