Django搭建个人博客Blog-Day03

news2024/11/17 14:39:53

对user模块进行开发

设计数据表

Django默认就提供了和用户相关的功能,但是这个Django默认提供的功能有个不好的点: 不太适合我们的项目,例如里面的字段不够等,所以我们要对它进行改造一下,方便项目开发。

拓展用户模型
  1. 进入虚拟环境安装pillow第三方库,为了方便保存和使用图片

pip  install pillow
  1. 在blog/blog/下创建一个名为media的文件夹,用来存放图片

  1. 在blog/blog/apps/user/models.py文件中添加如下代码:

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

# 模型层的代码   类的三大特性: 封装  继承  多态
# django 的 orm
# 类           对应   数据表     必须继承django提供的 moedls.Model
# 类中的属性    对应   字段
# 类实例化的对象 对应  一条记录

# 这应该是基于django提供的用户类进行扩展的
# 基于:以前django提供的很多功能有一些是可以直接使用的
# 扩展:因为字段不够  所以要扩展
class User(AbstractUser):
    # 增加一个字段  存放手机号码,unique=True:唯一索引,verbose_name:在admin管理后台中展示的名字
    phone = models.CharField(max_length=20,unique=True,verbose_name='手机号码',null=True)
    # 增加一个字段  存放用户头像
    # 注意事项: 要想使用ImageField 必须先安装一个模块:pillow
    avater = models.ImageField(upload_to='avatar/%Y%m%d/',verbose_name='头像',null=True)
    # 增加一个字段  存放个人简介
    bio = models.TextField(max_length=500,verbose_name='个人简介',null=True)

    # 这个类 生成的数据表 叫什么名字  user_user  如果我不想叫这个名字
    class Meta:  # 在类中定义一个类  类名必须叫Meta
        db_table = 'blog_users'       # db_table 这个的值 就是你要创建的数据表的表名
  1. 还要在配置文件中 指定上传的文件的目录在哪里,就是保存用户头像的文件夹,并且我们上传的文件肯定还需要访问看到,所以还要配置请求的URL前缀,在setting/dev.py中增加如下代码:

# 配置上传的文件的目录
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
# 配置上传的文件的请求的 url
MEDIA_URL = '/media/'
  1. 在setting/dev.py文件中添加如下代码,告诉Django要使用我们自己写的新的user模型类

# 格式:AUTH_USER_MODEL = '应用名.模型类型'
AUTH_USER_MODEL = 'user.User'

注意:

扩展了Django的用户模型类,等于破坏了Django的数据库,所以扩展用户模型类应该在第一次执行迁移文件之前就做好这个工作!

软删除

软删除的本质:就是多加一个标记字段,所谓的删除数据,无非就是将这个字段的值改变,以后查看的时候,就多个查询条件而已。

并没有真正的删除,当要删除一条记录时,就把标记字段改为1,展示时只展示标记字段为0的记录,这样在用户角度来看,看不到这些为1 的记录,就相当于删除。

  1. 对模型层进行改动,user/models.py:

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

class MySoftDeletableQuerySet(QuerySet):
    """
        当使用filter与all时所执行的操作类
    """
    def delete(self):
        # 重写删除方法
        self.update(is_delete=True)
        
class BaseManager(models.Manager):
    _queryset_class = MySoftDeletableQuerySet

    def get_queryset(self):
        return super().get_queryset().filter(is_delete=False).order_by('-create_time')

class BaseModel(models.Model):
    # auto_now_add  每次新增数据的时候  自动加入时间
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
    # auto_now     每次修改数据的时候  自动加入时间
    update_time = models.DateTimeField(auto_now=True,verbose_name='修改时间')
    # 增加字段  用来实现软删除的  默认是False  如果要删除数据,就将这个字段的值改成True
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    
    objects = BaseManager()
    
    def delete(self, using=None, keep_parents=False):
        self.is_delete = True  # 将这个字段的值改成True
        self.save()  # 保存

    # 一旦执行迁移  user_basemodel 继承
    class Meta:
        abstract = True
        # 这是一个抽象的基类  不会为这个类创建数据表  只是作为父类给别人继承而已
        ordering = ('-create_time')  # 根据创建时间进行排序

class User(AbstractUser,BaseModel):
    phone = models.CharField(max_length=20,unique=True,verbose_name='手机号码',null=True)
    avater = models.ImageField(upload_to='avatar/%Y%m%d/',verbose_name='头像',null=True)
    bio = models.TextField(max_length=500,verbose_name='个人简介',null=True)

    # 这个类 生成的数据表 叫什么名字  user_user  如果我不想叫这个名字
    class Meta:  # 在类中定义一个类  类名必须叫Meta
        db_table = 'blog_users'       # db_table 这个的值 就是你要创建的数据表的表名

2. 执行数据库迁移,生成对应的数据表(在虚拟环境中,manage.py文件所在路径下执行以下代码)

python manage.py makemigrations 
python manage.py migrate
实现注册功能
  1. 在视图层(blog/apps/user/views.py)添加如下代码(这里仅做测试,具体实现逻辑见下一步):

from django.shortcuts import render,HttpResponse
from django.views import View

# Create your views here.  
# 注册    get 展示注册页面  post  实现注册功能
class Register(View):
    # 展示用户注册的页面
    def get(self,request):
        return render(request,'user/register.html')
    
    # 接受用户的数据,实现注册功能
    def post(self,request):
        return HttpResponse('这是实现注册功能的')
  1. 写路由:blog/apps/user/urls.py

from django.urls import path
from . import views

app_name = 'user'
urlpatterns = [
    path('register',views.Register.as_view(),name='register')
])
  1. 写前端文件

  1. 首先在templates文件夹下创建base.html,用来展示博客的导航栏,就是头部和尾部,这些是保持不变的

{% load staticfiles %}
<!-- 设置引入静态文件 -->
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <!-- 网站采用的字符编码 -->
    <meta charset="utf-8">
    <!-- 预留网站标题的位置 -->
    <title>{% block title %}{% endblock %}</title>
    <!-- 引入bootstrap的css文件 -->
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <!-- bootstrap.js 依赖 jquery.js 和popper.js,因此在这里引入 -->
    <script src="{% static 'jquery-3.6.1.min.js' %}"></script>
    <!-- 引入layer.js -->
    <script src="{% static 'layer/layer.js' %}"></script>
    <!-- 引入popper.js -->
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1-lts/dist/umd/popper.min.js"></script>
    <!-- 引入bootstrap的js文件 -->
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    <script>
        $('div#article_body table').addClass('table table-bordered');
        $('div#article_body thead').addClass('thead-light');
    </script>
</head>
<body>
<!-- 定义导航栏 -->
<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="#">文章</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">写文章</a>
                </li>
                <!-- start 如果用户已经登录则显示用户名和头像 -->
                                <img src="" style="width: 38px;height: 38px; border-radius: 15%;">
                                <a class="nav-link" href="#">添加头像</a>
                    <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">
                        </a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                            <a class="dropdown-item" href="#">退出登录</a>
                            <a class="dropdown-item" href="#">个人中心</a>
                        </div>
                    </li>
                    <!-- 如果用户未登录,则显示 “登录” -->
                    <li class="nav-item">
                        <a class="nav-link" href="#">登录</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">注册</a>
                    </li>
            </ul>
        </div>
    </div>
</nav>
<!-- 预留具体页面的位置 -->
{% block content %}{% endblock content %}
<div>
    <br><br><br>
</div>
<footer class="py-3 bg-dark fixed-bottom">
    <div class="container">
        <p class="m-0 text-center text-white">Copyright &copy; xxx</p>
    </div>
</footer>
</body>
</html>
  1. 在templates/user里面创建register.html文件

{% extends 'base.html' %}
{% block title %}注册页面{% endblock title %}
{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-12">
                <br>
                <form method="post" action="">
                    <!-- 账号 -->
                    <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">邮箱</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>
                        <div class="alert alert-danger alert-dismissible">
                            <button type="button" class="close" data-dismiss="alert">&times;</button>
                            <strong>错误!</strong>
                        </div>
                    <!-- 提交按钮 -->
                    <button type="submit" class="btn btn-primary">提交</button>
                </form>
            </div>
        </div>
    </div>
{% endblock content %}
实现注册逻辑
  1. 修改blog/apps/user/view.py文件中用户注册的代码如下:

import re
from django.shortcuts import render,HttpResponse
from django.views import View
from user.models import User

class Register(View):
    # 展示用户注册的页面
    def get(self,request):
        return render(request,'user/register.html')

    # 接受用户的数据,实现注册功能
    def post(self,request):
        # 编写注册功能的逻辑   基本上所有的逻辑都差不多   1
        # 1. 接受用户数据
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        # 2. 做基本的验证
        # 2.1  验证参数是不是都有
        if not all([username,email,password,password2]):
            return render(request,'user/register.html',{'register_errmsg':'参数不全'})
        # 2.2 判断用户名是否是5~20个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return render(request, 'user/register.html', {'register_errmsg': '请输入5-20个字符的用户名'})
        # 2.3 判断邮箱是否合格
        if not re.match(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(com|cn|net)', email):
            return render(request, 'user/register.html', {'register_errmsg': '邮箱格式不正确'})
            # 判断密码是否是8-20个字符
        if not re.match(r'^[0-9A-Za-z]{6,20}$', password):
            return render(request, 'user/register.html', {'register_errmsg': '请输入6-20个字符的密码'})
            # 判断两次密码是否一致
        if password != password2:
            return render(request, 'user/register.html', {'register_errmsg': '两次输入的密码不一致'})
        # 3. 数据入库
        try:
            # 创建用户
            User.objects.create_user(username=username,password=password,email=email)
        except Exception as err:
            return render(request, 'user/register.html', {'register_errmsg': '用户名重复'})
        # 4. 返回结果  自动跳转到登录页
        return redirect(reverse('user:login'))
  1. 对register.html文件进行优化

{% extends 'base.html' %}
{% 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">邮箱</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>
                    <!-- 显示错误信息-->
                    {% if register_errmsg %}
                        <div class="alert alert-danger alert-dismissible">
                            <button type="button" class="close" data-dismiss="alert">&times;</button>
                            <strong>错误!</strong>{{ register_errmsg }}
                        </div>
                    {% endif %}
                    <!-- 提交按钮 -->
                    <button type="submit" class="btn btn-primary">提交</button>
                </form>
            </div>
        </div>
    </div>
{% endblock content %}
实现登录功能
  1. 写视图: blog/blog/apps/user/views.py

from django.contrib.auth import authenticate,login

# 登录功能
class Login(View):
    # 展示用户登录的页面
    def get(self,request):
        return render(request,'user/login.html')

    # 实现用户登录的功能逻辑
    def post(self,request):
        # 1. 接收用户的参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 2. 检验参数
        if not all([username, password]):
            return render(request, 'user/login.html', {'login_errmsg': '参数不全'})
        # 3. 认证登录用户
        user = authenticate(username=username,password=password)
        if user is None:
            return render(request, 'user/login.html', {'login_errmsg': '用户名或密码错误'})
        # 保持登录状态
        login(request,user)
        # 4. 返回结果
        return HttpResponse('登录成功')
  1. 写路由:blog/blog/apps/user/urls.py

from django.urls import path
from . import views

app_name = 'user'
urlpatterns = [
    path('register',views.Register.as_view(),name='register'),
    path('login',views.Login.as_view(),name='login'),
]
  1. 创建模板文件:templates/user/login.html

{% extends 'base.html' %}
{% 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="password">输入密码</label>
                        <input type="password" class="form-control" id="password" name="password" required>
                    </div>
                     <!-- 显示错误信息 -->
                    {% if login_errmsg %}
                        <div class="alert alert-danger alert-dismissible">
                            <button type="button" class="close" data-dismiss="alert">&times;</button>
                            <strong>错误!</strong>{{login_errmsg}}
                        </div>
                    {% endif %}
                    <!-- 提交按钮 -->
                    <button type="submit" class="btn btn-primary">提交</button>
                </form>
            <h5>忘记密码了?</h5>
            <h5>点击<a href='#'>这里</a>重置密码</h5>
            </div>
        </div>
    </div>
{% endblock content %}

接下来就可以启动项目,实现注册和登录功能,项目结构如下:

需要静态资源文件可私信!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/160367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java1算法

排序–comparable接口 java提供了一个接口Comparable用来定义类的排序规则 eg: 1、定义一个学生类Student&#xff0c;具有年龄age和姓名username连个属性&#xff0c;并通过Comparable接口提供比较规则&#xff1b; 2、定义测试类Test,在测试类中定义测试方法Comparable getM…

还不会用YakitBp?来,我教你

前言 &#x1f340;作者简介&#xff1a;被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 &#x1f341;个人主页&#xff1a;被吉师散养的职业混子 &#x1f342;相应专栏&#xff1a;CTF专栏 Yakit介绍 好兄弟&#xff0c;你听说过yakit吗&…

Redis五大基本数据类型

Redis五大基本数据类型 1.Redis通用命令 常用命令 #Redis的键key操作 keys * 表示查看当前库所有key 【注意是&#xff1a;可以使用通配符】 exists <key> 表示判断某个key是否存在&#xff0c;存在返回1&#xff0c;否则返回0 type <key> 表示判断key类型 del …

fiddler的下载和安装,及常用操作

目录 一、fiddler介绍 二、fiddler的下载和安装 三、fiddler的简单配置 四、fiddler的抓包 五、fiddler的自动响应器 六、fiddler的断点 七、fiddler的构造器 一、fiddler介绍 Fiddler是比较好用的Web代理调试工具之一&#xff0c;它能记录并检查所有客户端与服务端的HT…

【SpringCloud09】Ribbon负载均衡服务调用

1.概述 1.1是什么 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时&…

Java 如何设计一款小游戏详细讲解(一)

目录 介绍 讲解 步骤一 步骤二 阶段(一)详细代码 介绍 注&#xff1a;这里是参考黑马程序员课程&#xff0c;其中图片也是直接拿的黑马程序员提供的图片 其中游戏的代码主要参考黑马程序员的课程&#xff0c;登录和注册主要由自己完成。 黑马素材放到这里自取 链接: https…

【Esp32】Spi接口驱动SX1268模块

【Esp32】Spi接口驱动SX1268模块1.硬件接线2. SX1268 模块的 SPI 时序分析3. 基于 ESP32 实现函数封装3.1 读寄存器3.2 写寄存器4. 实验结果日期&#xff1a; 2023-01-13 项目需要用乐鑫的 ESP32开发板驱动 Lora 模块&#xff0c;用的是 深圳SX1268ZTR4-GC的lora模块&#xff…

通行密钥,向无休止的修改密码说再见~

在上一期里《对称加密面临的那些挑战》中&#xff0c;我们提过密码&#xff0c;和多数人理解的不同&#xff0c;日常生活中用于保护账号安全的所谓“密码”&#xff0c;更贴切的称呼应该是“口令”密码。密码学中的密码&#xff0c;和我们日常生活中登录各类信息化系统所使用的…

Vue--》基于Vue的UI组件库,大家应该熟悉并会使用

目录 PC端UI组件库 Element UI IView UI 移动端UI组件库 Vant Cube UI Mint UI Nut UI UI组件库&#xff1a;它是设计系统的一部分&#xff0c;是在我们常规界面设计过程中可以直接用来制作交互图例和搭建页面的组件集合&#xff0c;它可以作为单个组件独立存在&#x…

Linux下的FrameBuffer驱动框架

一、RGB LCD经典显示器件介绍&#xff1a;1、LCD屏幕的重要属性参数&#xff1a;① 分辨率&#xff1a;也就是屏幕上的像素点的个数&#xff1b;② 像素格式&#xff1a;即单个像素点RGB三种颜色的表达方式&#xff0c;包括RGB888、ARGB8888和RGB565等。③ LCD屏幕硬件接口&…

全网最全的Linux中的内核级加强型火墙图文详解

目录 前言 一、Selinux的功能 二、Selinux的状态及管理 三、Selinux的安全上下文 四、SEBOOL 五、SEPORT 六、setrouble 前言 内核级加强型火墙主要是指系统中的selinux功能&#xff0c;该功能开启时&#xff0c;会对系统中的文件和程序产生影响&#xff0c;用户的…

SkyEye:针对飞行模拟器的仿真解决方案

01.飞行模拟器简介 飞行模拟器是一种由人工打造&#xff0c;能够尽可能真实地还原飞机飞行及空中环境的模拟系统&#xff0c;一般用于飞行员培训、飞机设计等工作。飞行模拟器能够模拟如何控制飞机飞行、模拟飞机应用系统的反应&#xff0c;还可模拟一些可能会对飞机系统造成影…

java图片压缩

1背景 查看各种文章&#xff0c;发现thumbnailator的压缩率和压缩效果都不错&#xff0c;thumbnailator又是使用java实现的&#xff0c;所以直接扒源码&#xff0c;找到了里面实现压缩的关键代码&#xff0c;封装成一个压缩工具类&#xff0c;有需要的同学可以参考。thumbnail…

Linux多线程Web服务器(C++实现)

本文实现的是基于Reactor模式epoll&#xff08;边缘触发&#xff09;非阻塞socket非阻塞IO线程池的Web服务器&#xff0c;可以处理GET、POST两种请求&#xff0c;完成展示主页、获取图片、获取视频、登录及注册共五种功能。原理图&#xff1a;上图为本文实现的服务器的原理图&a…

国产GPU芯片迎来突破,算力全球第一,中文编程也有好消息

苦&#xff0c;芯片久矣&#xff0c;终&#xff0c;迎来突破&#xff0c;实在振奋人心&#xff01;最近&#xff0c;国产GPU芯片传来了好消息&#xff0c;国产自研首款通用芯片&#xff0c;以每秒千万亿次的计算能力&#xff0c;创全球算力记录&#xff0c;芯片领域实现跨越式的…

包体积优化 · 实战论 · 怎么做包体优化? 做好能晋升吗? 能涨多少钱?

“ 【小木箱成长营】包体积优化系列文章&#xff1a; 包体积优化 方法论 揭开包体积优化神秘面纱 包体积优化 工具论 初识包体积优化 BaguTree 包体积优化录播视频课 ”一、引言 Hello&#xff0c;我是小木箱&#xff0c;欢迎来到小木箱成长营系列教程&#xff0c;今天将分…

论文投稿指南——中文核心期刊推荐(农业工程)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

实战10:基于opencv的数字图像处理:边缘检测 (完整代码+详细教程)

给出“离散拉普拉斯算子”一般形式的数学推导 离散值的导数使用差分代替: 所以: 以(x, y)为中心点,在水平和垂直方向上应用拉普拉斯算子,滤波器(对应a=1的情况)为:

Spring Cloud Alibaba学习指南

文章目录背景介绍主要功能主要组件参考文档Spring Cloud Alibaba githubNacos官方文档Nacos运维手册Sentinel官方文档Spring Cloud Alibaba SentinelSeata官方文档Spring Cloud Alibaba 英语文档应用脚手架背景 由于在2018年Netflix公司宣布对其核心组件Hystrix、Ribbon、zuul…

远端连接服务器详解

昨天决定入手了一台腾讯轻量应用服务器&#xff0c;在连接的过程中遇到很多问题&#xff0c;浪费了很多时间&#xff0c;所以在这里对这些问题进行整理分享给大家&#xff01;&#xff01;&#xff01;系统的安装OpenCloudOS是完全中立、全面开放、安全稳定、高性能的操作系统及…