基于Django框架的博客平台开发与实现(二)

基于Django框架的博客平台开发与实现(二)

感谢

摘要   

前端架构搭建:

用户登录和注册实现

用户登录和注册静态网页模版实现  

 配置自定义用户模型

用户注册功能实现

用户登录功能实现

后续


感谢

感谢锋哥的指导。由于我使用的是MySQL 5.7版本,因此对项目代码进行了相应的调整。详细修改过程及源代码,请参考锋哥在B站发布的视频教程:
基于Django框架的博客系统的开发与实现https://www.bilibili.com/video/BV1GJ6uYpEwK在此,也向锋哥表示诚挚的谢意!

摘要   

        本项目利用Django框架,结合现代Web开发的最佳实践,构建了一个功能全面、易于扩展的博客平台。通过此项目,开发者可以学习到如何使用Django进行模型设计、视图逻辑编写、模板渲染以及静态文件管理等核心技能,同时掌握了用户认证、文章管理等博客系统必备功能的实现方法。

项目代码地址:Vlog_systemGitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode.com/m0_50313048/Vlog_system/tree/master
上一篇: 

基于Django框架的博客平台开发与实现(一)https://blog.youkuaiyun.com/m0_50313048/article/details/145979217

前端架构搭建:

 前端Bootstrap5 UI框架:Bootstrap · The most popular HTML, CSS, and JS library in the world.Powerful, extensible, and feature-packed frontend toolkit. Build and customize with Sass, utilize prebuilt grid system and components, and bring projects to life with powerful JavaScript plugins.https://getbootstrap.com/

这边下载的版本是5.3.3

在settings.py中,配置静态资源和媒体资源:

STATIC_URL = '/static/'  # 设置静态资源的URL
STATICFILES_DIRS = [BASE_DIR / 'publicStatic']  # 设置静态资源的保存路径
STATIC_ROOT = BASE_DIR / 'static'  # 设置静态资源的打包路径
# 设置媒体资源的保存路径
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"

我们在项目目录下,新建static、publicStatic、media三个文件夹。然后从网站上下载bootstrap5开发包,放入publicStatic

 我们来测试下前端:

templates文件夹下新建test.html

<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="{% static 'bootstrap-5.3.3/css/bootstrap.css' %}" rel="stylesheet"/>
    <script src="{% static 'bootstrap-5.3.3/js/bootstrap.js' %}"></script>
</head>
<body>
<button class="btn btn-primary">测试按钮</button>
</body>
</html>

article的views.py的TestView类的get方法修改下:

return render(request, 'test.html')

启动项目,浏览器请求地址: http://127.0.0.1:8000/article/test

 

用户登录和注册实现

用户登录和注册静态网页模版实现  

准备两个静态html页面,即登录静态模版页面login.html和注册静态模版页面register.html。

 login.html:

<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <title>博客系统用户登录界面</title>
    <script src="{% static "js/jquery-1.11.2.min.js" %}"></script>
    <link rel="stylesheet" href="{% static "css/login.css" %}" type="text/css">
    <script type="text/javascript">
        $(function () {
            //得到焦点
            $("#password").focus(function () {
                $("#left_hand").animate({
                    left: "150",
                    top: " -38"
                }, {
                    step: function () {
                        if (parseInt($("#left_hand").css("left")) > 140) {
                            $("#left_hand").attr("class", "left_hand");
                        }
                    }
                }, 2000);
                $("#right_hand").animate({
                    right: "-64",
                    top: "-38px"
                }, {
                    step: function () {
                        if (parseInt($("#right_hand").css("right")) > -70) {
                            $("#right_hand").attr("class", "right_hand");
                        }
                    }
                }, 2000);
            });
            //失去焦点
            $("#password").blur(function () {
                $("#left_hand").attr("class", "initial_left_hand");
                $("#left_hand").attr("style", "left:100px;top:-12px;");
                $("#right_hand").attr("class", "initial_right_hand");
                $("#right_hand").attr("style", "right:-112px;top:-12px");
            });
        });
        function checkForm() {
            var username = $("#username").val();
            var password = $("#password").val();
            if (username == null || username == "") {
            $("#error").html("用户名不能为空!");
            return false;
            }
            if (password == null || password == "") {
                $("#error").html("密码不能为空!");
                return false;
            }
            return true;
        }
    </script>
</head>
<body>
<DIV class="top_div">
</DIV>
<form action="login" method="post" onsubmit="return checkForm()">
    {% csrf_token %}
    <DIV style="background: rgb(255, 255, 255); margin: -100px auto auto;
border: 1px solid rgb(231, 231, 231); border-image: none; width: 400px; height:
230px; text-align: center;">
        <DIV style="width: 165px; height: 96px; position: absolute;">
            <DIV class="tou">
            </DIV>
            <DIV class="initial_left_hand" id="left_hand">
            </DIV>
            <DIV class="initial_right_hand" id="right_hand">
            </DIV>
        </DIV>
        <P style="padding: 30px 0px 10px; position: relative;">
            <SPAN class="u_logo"></SPAN>
            <INPUT id="username" name="username" class="ipt" type="text"
            placeholder="请输入用户名"
            value="{{ username }}">
        </P>
        <P style="position: relative;">
            <SPAN class="p_logo"></SPAN>
            <INPUT id="password" name="password" class="ipt" type="password" placeholder="请输入密码" value="{{ password }}">
        </P>
        <DIV style="height: 50px; line-height: 50px; margin-top: 30px; border-top-color: rgb(231, 231, 231); border-top-width: 1px; border-top-style: solid;">
            <P style="margin: 0px 35px 20px 45px;">
                <SPAN style="float: left;">小龙ssss博客系统&nbsp;&nbsp;&nbsp;&nbsp;<a href="register.html"
                style="color: darkcyan">>>用户注册</a></SPAN>
                <SPAN style="float: right;">
                    <input type="submit"
                    style="background: rgb(0, 142, 173); padding: 7px 10px;
                    border-radius: 4px; border: 1px solid rgb(26, 117, 152); border-image: none;
                    color: rgb(255, 255, 255); font-weight: bold;"
                    value="登录"/>
                </SPAN>
            </P>
        </DIV>
<span style="padding-top: 5px"><font color="red" id="error">{{ errorinfo}}</font></span>
    </DIV>
</form>
<div style="text-align:center;padding-top: 30px">
Copyright © 2015-2025 <a href="https://blog.youkuaiyun.com/m0_50313048"
target="_blank">小龙ssss</a> 版权所有
</div>
</body>
</html>

 register.html:

<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}
    <title>博客系统用户注册</title>
    <script src="{% static "js/jquery-1.11.2.min.js" %}"></script>
    <link rel="stylesheet" href="{% static "css/login.css" %}" type="text/css">
    <script type="text/javascript">
        $(function () {
            //得到焦点
            $("#password").focus(function () {
                $("#left_hand").animate({
                    left: "150",
                    top: " -38"
                }, {
                    step: function () {
                        if (parseInt($("#left_hand").css("left")) > 140) {
                            $("#left_hand").attr("class", "left_hand");
                        }
                    }
                }, 2000);
                $("#right_hand").animate({
                    right: "-64",
                    top: "-38px"
                }, {
                    step: function () {
                        if (parseInt($("#right_hand").css("right")) > -70) {
                            $("#right_hand").attr("class", "right_hand");
                        }
                    }
                }, 2000);
            });
            //失去焦点
            $("#password").blur(function () {
                $("#left_hand").attr("class", "initial_left_hand");
                $("#left_hand").attr("style", "left:100px;top:-12px;");
                $("#right_hand").attr("class", "initial_right_hand");
                $("#right_hand").attr("style", "right:-112px;top:-12px");
            });

            //得到焦点
            $("#password2").focus(function () {
                $("#left_hand").animate({
                    left: "150",
                    top: " -38"
                }, {
                    step: function () {
                        if (parseInt($("#left_hand").css("left")) > 140) {
                            $("#left_hand").attr("class", "left_hand");
                        }
                    }
                }, 2000);
                $("#right_hand").animate({
                    right: "-64",
                    top: "-38px"
                }, {
                    step: function () {
                        if (parseInt($("#right_hand").css("right")) > -70) {
                            $("#right_hand").attr("class", "right_hand");
                        }
                    }
                }, 2000);
            });
            //失去焦点
            $("#password2").blur(function () {
                $("#left_hand").attr("class", "initial_left_hand");
                $("#left_hand").attr("style", "left:100px;top:-12px;");
                $("#right_hand").attr("class", "initial_right_hand");
                $("#right_hand").attr("style", "right:-112px;top:-12px");
            });
        });

        function checkForm() {
            var username = $("#username").val();
            var password = $("#password").val();
            var password2 = $("#password2").val();
            if (username == null || username == "") {
                $("#error").html("用户名不能为空!");
                return false;
            }
            if (password == null || password == "") {
                $("#error").html("密码不能为空!");
                return false;
            }
            if (password2 == null || password2 == "") {
                $("#error").html("确认密码不能为空!");
                return false;
            }
            if (password != password2) {
                $("#error").html("确认密码输入不正确!");
                return false;
            }
            return true;
        }
    </script>
</head>
<body>
<DIV class="top_div">
</DIV>
<form action="register" method="post" onsubmit="return checkForm()">
    {% csrf_token %}
    <DIV style="background: rgb(255, 255, 255); margin: -100px auto auto; border: 1px solid rgb(231, 231, 231); border-image: none; width: 400px; height: 280px; text-align: center;">
        <DIV style="width: 165px; height: 96px; position: absolute;">
            <DIV class="tou">
            </DIV>
            <DIV class="initial_left_hand" id="left_hand">
            </DIV>
            <DIV class="initial_right_hand" id="right_hand">
            </DIV>
        </DIV>
        <P style="padding: 30px 0px 10px; position: relative;">
            <SPAN class="u_logo"></SPAN>
            <INPUT id="username" name="username" class="ipt" type="text" placeholder="请输入用户名"
                   value="{{ username }}">
        </P>
        <P style="position: relative;">
            <SPAN class="p_logo"></SPAN>
            <INPUT id="password" name="password" class="ipt" type="password" placeholder="请输入密码"
                   value="{{ password }}">
        </P>
        <P style="padding-top:10px;position: relative;">
            <SPAN class="p_logo" style="margin-top: 10px;"></SPAN>
            <INPUT id="password2" name="password2" class="ipt" type="password" placeholder="请输入确认密码"
                   value="{{ password2 }}">
        </P>
        <DIV style="height: 50px; line-height: 50px; margin-top: 30px; border-top-color: rgb(231, 231, 231); border-top-width: 1px; border-top-style: solid;">
            <P style="margin: 0px 35px 20px 45px;">
                <SPAN style="float: left;">小龙ssss博客系统&nbsp;&nbsp;&nbsp;&nbsp;<a href="login.html"
                                                                                           style="color: darkcyan">>>用户登录</a></SPAN>
                <SPAN style="float: right;">
	              <input type="submit"
                         style="background: rgb(0, 142, 173); padding: 7px 10px; border-radius: 4px; border: 1px solid rgb(26, 117, 152); border-image: none; color: rgb(255, 255, 255); font-weight: bold;"
                         value="注册"/>
	         </SPAN>
            </P>
        </DIV>
        <span style="padding-top: 5px"><font color="red" id="error">{{ info }}</font></span>
    </DIV>
</form>
<div style="text-align:center;padding-top: 30px">
    Copyright © 2015-2025 <a href="https://blog.youkuaiyun.com/m0_50313048" target="_blank">小龙ssss</a> 版权所有
</div>
</body>
</html>

 把login.html和register.html模版文件放入templates下;另外再把开发包中的css,js,images静态文件放publicStatic下面;(此操作用windows资源管理器操作就行,最好别用pycharm,可能会卡)

 

 user / views.py 添加跳转逻辑:

def toLoginPage(request):
    """
    跳转登录页面
    :param request:
    :return:
    """
    return render(request, 'login.html')


def toRegisterPage(request):
    """
    跳转到注册页面
    :param request:
    :return:
    """
    return render(request, 'register.html')

 user / urls.py 添加 请求映射:

from django.urls import path
from article.views import TestView
from user.views import toLoginPage, toRegisterPage
urlpatterns = [
    # 跳转登录页面
    path('login.html', toLoginPage, name='toLoginPage'),
    # 跳转注册页面
    path('register.html', toRegisterPage, name='toRegisterPage'),
]

 根路径请求,我们选择直接跳转到登录页面:

# article / urls.py里加下映射:
# 记得要
# from django.views.generic import RedirectView
path('', RedirectView.as_view(url='user/login.html')),

 总的项目的urls.py里,我们也需要进行修改:

 这样我们直接请求 http://127.0.0.1:8000/ ,跳转到登录页面:

 点击用户注册,跳转到注册页面:

 配置自定义用户模型

 在项目开发过程中,我们发现Django默认的admin系统中的用户模型无法充分满足特定的业务需求。为了实现对用户属性的自定义扩展,我们决定采用继承AbstractUser类的方式来创建自定义用户模型。这种方案既能保留Django内置的用户认证功能,又可以根据实际业务需求灵活地添加所需的字段和功能,为系统的用户管理提供更完善的支持。

user / models.py:

from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.
class MyUser(AbstractUser):
    name = models.CharField('姓名', max_length=50, default='匿名用户')
    introduce = models.TextField('简介', default='暂无介绍')
    company = models.CharField('公司', max_length=100, default='暂无信息')
    profession = models.CharField('职业', max_length=100, default='暂无信息')
    address = models.CharField('住址', max_length=100, default='暂无信息')
    telephone = models.CharField('电话', max_length=11, default='暂无信息')
    wx = models.CharField('微信', max_length=50, default='暂无信息')
    qq = models.CharField('QQ', max_length=50, default='暂无信息')
    avatar = models.ImageField('头像', blank=True, upload_to='avatar/')

    # 设置返回值
    def __str__(self):
        return self.name

 media目录下新建avatar目录,用于存储图像

 settings.py:

# 配置自定义用户模型MyUser
AUTH_USER_MODEL = 'user.MyUser'

makemigrations生成迁移文件;migrate执行迁移文件;

启动报错,缺少pillow库,我们安装下

pip install pillow==11.0.0

再执行:

makemigrations
migrate

migrate执行后,生成了所有表,包括admim系统的用户表

 

 

用户注册功能实现

本功能实现用户注册的后台逻辑处理流程如下:当客户端发起POST请求时,服务端通过request.POST获取username、password、password2三个表单参数。系统将依次执行以下验证步骤:

  1. 用户唯一性校验:通过User.objects.filter(username=username).exists()查询数据库,若存在重复用户名则返回错误提示
  2. 密码一致性验证:比对password与password2参数,若不一致则中断注册流程
  3. 数据持久化存储:使用User.objects.create_user(**d)方法创建用户记录,其中字典d通过双星号运算符解包键值对,自动匹配模型字段与表单参数
  4. 模板数据绑定:通过render(request, 'register.html', locals())将当前作用域的变量(如用户输入值、错误信息等)注入模板上下文,实现页面元素的动态渲染。

在user/views.py文件中写入如下代码:

from django.contrib.auth import logout
from user.models import MyUser
def register(request):
    """
    用户注册
    :param request:
    :return:
    """
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    password2 = request.POST.get('password2', '')
    if MyUser.objects.filter(username=username):
        info = '用户已存在'
    elif password2 != password:
        info = '两次密码输入不一致'
    else:
        d = {
            'username': username, 'password': password,
            'is_superuser': 1, 'is_staff': 1
        }
        user = MyUser.objects.create_user(**d)
        user.save()
        info = '注册成功,请重新登录'
        logout(request)  # 清除登录信息
    return render(request, 'register.html', locals())

我们再配置user/urls.py映射:

# 用户注册请求
path('register', register, name='userRegister'),

# 记得在代码开头加上
# from user.views import register

 测试一下:

 

 可以看到,密码是加密的。

用户登录功能实现

​​​​用户认证功能实现技术方案:

本系统采用Django认证框架实现用户登录流程,具体执行逻辑如下:

  1. 凭证获取与初步验证
    通过request.POST获取username和password参数,执行User.objects.filter(username=username).exists()进行用户存在性校验

  2. 身份认证管道
    使用authenticate(request, username=username, password=password)构建认证用户对象,该方法自动完成:

                密码哈希值比对

                用户模型关联校验

                CSRF令牌验证

     3. ​账户状态验证
        对认证成功的用户对象(user)进行激活状态检测,通过user.is_active属性判断账户可用性

     4. ​会话管理机制
        通过auth.login(request, user)方法建立持久化会话:

                生成session_key存入数据库

                设置sessionid cookie

                注册用户对象至请求上下文

      5. 异常处理规范

        针对不同失败场景返回对应错误类型:

  • 用户不存在:提示"用户不存在,请注册"
  • 账号或密码错误:提示"用户名或者密码错误!"

已注册账号:xlsss 密码:123456

user/views.py增加如下代码:

from django.contrib.auth import authenticate, login as auth_login

def login(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    if MyUser.objects.filter(username=username):
        user = authenticate(username=username, password=password)
        if user:
            if user.is_active:
                # django.contrib.auth.login(request, user)
                auth_login(request, user)
            print("登录认证成功,跳转到博客主页")
        else:
            errorinfo = '用户名或者密码错误!'
    else:
        errorinfo = '用户不存在,请注册'
    return render(request, 'login.html', locals())

user/urls.py增加如下代码:

# 用户登录请求
path('login', login, name='userLogin'),

 

跳转成功!

后续

持续更新中。。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值