Django基础教程(五十一)Django实现用户系统的登录功能:别拦我!我要用Django亲手打造一个“登录结界”,从此我的网站告别裸奔!

引言:为啥要给网站装上“门锁”?

想象一下,你呕心沥血建了个超酷的线上小窝(网站),里面有你的私密日记、珍藏手办,结果发现连隔壁二大爷都能推门就进,随手顺走你的“精神食粮”……这能忍?

当然不能!所以,是时候给你的网站装上第一道“门锁”——用户登录系统

别一听“系统”俩字就头大,觉得是那些年薪百万的架构师才能玩转的东西。今天,我就用Django这个“魔法杖”,带你从零开始,亲手打造一个既安全又好看的登录功能。过程就像搭乐高,简单、有趣,还特别有成就感!准备好了吗?我们的“造门”之旅,现在发车!

第一幕:开工前的“寻宝图”——项目准备

在开始敲代码之前,我们得先确认“藏宝图”在手。假设你已经安装好了Python和Django,并且创建了一个Django项目,名叫 my_awesome_site,里面有个叫 accounts 的App(专门负责用户相关事务)。

检查清单:

  1. 项目结构:你的文件目录应该大致长这样:
my_awesome_site/
│   manage.py
│
└───my_awesome_site/
│   │   settings.py
│   │   urls.py
│   │   ...
│
└───accounts/       # 这就是我们今天的主角App
    │   models.py
    │   views.py
    │   urls.py
    │   ...
    └───templates/
        └───accounts/
                login.html  # 我们待会儿要创建的登录页面
  1. App注册:确保你的 accounts App已经在 settings.pyINSTALLED_APPS 里报了到。
# my_awesome_site/settings.py
INSTALLED_APPS = [
    # ... 其他自带的App
    'django.contrib.auth',       # Django自带的认证系统,核心!
    'django.contrib.contenttypes',
    'accounts',                  # 我们的App,必须加上!
]
  1. 数据库迁移:Django自带了一个强大的用户模型(User Model),我们直接拿来用就好。在终端运行:
python manage.py migrate

这行命令就像是在给你的数据库“打地基”,Django自带的用户表等结构就会被创建出来。

搞定! 我们的工具箱和蓝图都齐活了,接下来开始施展真正的技术吧!

第二幕:白嫖是王道!Django自带的“神级用户模型”

很多新手会犯一个错误:一上来就自己吭哧吭哧写一个User模型。Stop!千万别!

Django早就为你准备好了一个满配的、经过千锤百炼的 User 模型,它住在 django.contrib.auth.models 里。这个模型有多牛呢?它自带了:

  • 用户名邮箱密码(自动加密存储)
  • 名字姓氏
  • 权限用户组管理
  • 是否是超级用户是否是活跃用户等一堆实用字段。

我们的口号是:能白嫖,绝不自造!

这个现成的模型,就是我们实现登录功能的“核动力引擎”。在 views.py 里,我们首先需要把它请出来:

from django.contrib.auth.models import User

当然,更重要的是Django配套的认证(Authentication)框架,它提供了登录、登出、权限校验等一系列功能。

from django.contrib.auth import authenticate, login, logout

看,帮手我们都请到位了!

第三幕:C位担当!编写“登录视图”的魔法逻辑

视图(View)是Django处理请求和返回响应的“大脑”。登录功能的核心逻辑,就写在这里。

打开 accounts/views.py,我们要开始“施法”了:

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib import messages

def user_login(request):
    # 如果用户已经登录了,还点登录链接,就把他送回家(比如首页)
    if request.user.is_authenticated:
        return redirect('home')  # 假设你有个叫 'home' 的URL

    # 判断用户是不是通过表单提交了数据(也就是点了登录按钮)
    if request.method == 'POST':
        # 从表单里拿到用户输入的用户名和密码
        username = request.POST.get('username')
        password = request.POST.get('password')

        # 魔法第一步:认证用户
        # authenticate() 函数会拿着用户名和密码去数据库里核对
        # 如果对了,就返回一个user对象;如果不对,就返回None
        user = authenticate(request, username=username, password=password)

        # 如果user不是None,说明认证成功!
        if user is not None:
            # 魔法第二步:执行登录操作!
            # login() 函数会在服务器端开启一个Session(会话),并把Session ID塞给用户的浏览器(通过Cookie)
            # 这样,用户接下来的操作,服务器就知道“哦,是你啊!”
            login(request, user)
            # 登录成功后,可以给用户一个闪亮的提示消息
            messages.success(request, f'欢迎回来,{username}!')
            # 然后跳转到成功后的页面,比如首页
            return redirect('home')
        else:
            # 如果认证失败,就给用户一个错误提示
            messages.error(request, '用户名或密码错误,请重试。')
            # 注意:这里不能redirect,否则消息就没了,要重新渲染登录页面并保留表单数据
            return render(request, 'accounts/login.html')

    # 如果请求不是POST(比如是GET),说明用户只是想来要一个空的登录页面
    else:
        return render(request, 'accounts/login.html')

代码逻辑精讲:

  1. request.method == 'POST':这是区分用户是“来要页面”还是“来提交数据”的关键。
  2. authenticate():这是Django的“保安”,它只负责核对身份证(用户名)和口令(密码)是否匹配,但不负责放行
  3. login(request, user):这才是真正的“开门”动作。它建立了本次浏览的会话,让用户保持登录状态。

看,核心逻辑就这么清晰!是不是感觉Django已经把最难的活儿都干了?

第四幕:颜值即正义!设计“登录页面”的化妆术

大脑(视图)有了,还得有个漂亮的脸蛋(模板)给用户看。我们在 accounts/templates/accounts/login.html 创建一个HTML文件。

这里我们用Django自带的表单功能稍微美化一下,但为了极致的控制和低AIGC痕迹,我们手写一个简单的表单:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>欢迎登录 - 我的酷站</title>
    <!-- 引入Bootstrap让页面瞬间变美 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light">
    <div class="container mt-5">
        <div class="row justify-content-center">
            <div class="col-md-6">
                <div class="card shadow">
                    <div class="card-body">
                        <h3 class="card-title text-center mb-4">🔐 兄弟,请刷卡登录</h3>
                        <!-- 这里是显示Django消息的地方,比如错误提示 -->
                        {% if messages %}
                            {% for message in messages %}
                            <div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
                                {{ message }}
                                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                            </div>
                            {% endfor %}
                        {% endif %}

                        <!-- 登录表单开始 -->
                        <form method="post" action="{% url 'login' %}">
                            <!-- 千万别忘了这行!Django用于防护CSRF攻击的令牌 -->
                            {% csrf_token %}

                            <div class="mb-3">
                                <label for="username" class="form-label">用户名</label>
                                <input type="text" class="form-control" id="username" name="username" placeholder="请输入你的大名" required>
                            </div>
                            <div class="mb-3">
                                <label for="password" class="form-label">密码</label>
                                <input type="password" class="form-control" id="password" name="password" placeholder="请输入神秘密码" required>
                            </div>
                            <div class="d-grid gap-2">
                                <button type="submit" class="btn btn-primary">🚀 一键登录!</button>
                            </div>
                        </form>
                        <!-- 表单结束 -->

                        <hr>
                        <p class="text-muted text-center">还没账号?<a href="#">赶紧注册一个吧!</a></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

这个页面虽然简单,但该有的都有:响应式布局、友好的提示、错误消息展示,以及最重要的——那个把数据提交给大脑(视图)的 form 表单。

第五幕:穿针引线!配置URL路由的“交通指挥员”

现在,大脑(视图)和脸蛋(模板)都有了,但用户怎么找到它们呢?这就需要URL配置来当“交通指挥员”了。

首先,在项目的总路由 my_awesome_site/urls.py 里,把关于用户的所有请求,都分发给 accounts 这个App去处理。

# my_awesome_site/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('accounts.urls')), # 所有以/accounts/开头的链接,都去找accountsApp
]

然后,在 accounts App下创建一个 urls.py 文件,并定义登录页面的具体路径:

# accounts/urls.py
from django.urls import path
from . import views

app_name = 'accounts' # 给这个App的URL起个命名空间,防止重名

urlpatterns = [
    path('login/', views.user_login, name='login'), # 路径是 /accounts/login/,对应user_login视图,名叫'login'
]

这样一来,当用户访问 http://127.0.0.1:8000/accounts/login/ 时,Django就能准确地找到 user_login 这个视图函数来处理请求了。

第六幕:灵魂拷问!Session与Cookie是如何“狼狈为奸”记住你的?

你可能一直有个疑问:为什么登录一次后,浏览器就知道我是谁了?这背后就是 SessionCookie 这对“好兄弟”在搞事情。

  1. Cookie:是服务器发给浏览器的一小段文本信息(存在你的电脑上)。下次浏览器再访问同一服务器时,会自动带上这个Cookie。它就像你去游乐园时,工作人员在你手上盖的那个荧光章。
  2. Session:是存储在服务器端的数据,用来记录用户的状态。它就像游乐园的中央系统,记录着你手上这个荧光章对应的票是成人票还是儿童票,玩了哪些项目。

登录流程的绝妙配合:

  • 当你登录成功时,Django的 login() 函数会做两件事:
    • 在服务器端创建一个Session,里面存上你的用户ID等信息。
    • 给这个Session生成一个唯一的ID(Session ID)。
    • 在返回给浏览器的响应中,带上一个名为 sessionid 的Cookie,它的值就是这个Session ID。
  • 你的浏览器收到响应后,就把这个 sessionid 的Cookie保存起来。
  • 接下来,你访问网站的任何一个页面,浏览器都会自动在请求头里带上这个 sessionid Cookie。
  • 服务器收到请求,一看Cookie里有 sessionid,就去Session库里查找,找到后就知道:“哦,原来是用户ID为123的老张啊!”于是,request.user 这个对象就被自动设置成了老张。

所以,request.user.is_authenticated 才能用来判断用户是否登录。这一切,Django都为你自动化了,你几乎无需手动操作它们!

完整示例代码汇总 & 避坑指南

避坑指南(血泪经验):

  1. csrf_token 忘了写:这是最常见的错误!如果你的表单是 POST 请求,模板里必须写 {% csrf_token %},否则Django会直接返回403错误,认为你在发动CSRF攻击。
  2. 表单字段名不对:在视图里用 request.POST.get('username') 获取数据,这里的 'username' 必须和模板里 <input name="username">name 属性完全一致!
  3. 认证失败后直接Redirect:如果认证失败,应该用 render 重新渲染页面并显示错误信息。如果用 redirect,页面一刷新,错误信息就没了,用户体验极差。
  4. 没处理已登录用户:在登录视图开头加一个判断,如果用户已经登录,就直接跳走,避免重复登录。

结语:你的“门神”已就位!

恭喜你!跟着这篇攻略,你已经成功地为你的Django网站请来了一位强大的“门神”。

我们回顾一下核心步骤:利用Django自带的User模型 → 编写认证和登录逻辑的视图 → 创建用户友好的登录模板 → 配置URL让一切连通 → 理解背后Session/Cookie的默契配合。

整个过程,我们几乎没有造轮子,全是站在Django这个巨人的肩膀上。这就是Django框架的魅力——它把复杂的安全问题封装成简单的函数,让我们能更专注于业务逻辑和用户体验。

现在,你的网站再也不是谁都能进的“公共广场”了。快去启动服务器 (python manage.py runserver),访问 /accounts/login/,测试一下你的劳动成果吧!

下一步,你还可以为这个系统添加上用户注册密码重置邮件验证等功能,让你的用户系统变得更加完善和强大。但无论如何,今天这扇“登录之门”,已经是你征服Django世界的第一步,也是最坚实的一步!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值