首页 > 其他分享 >仿bbs项目之注册登录

仿bbs项目之注册登录

时间:2023-01-02 22:57:18浏览次数:42  
标签:obj name 登录 models length form 注册 文章 bbs

目录

仿bbs项目之注册登录

今日内容概要

  • 项目开发流程
  • 项目流程
  • 注册功能
  • 登录功能

今日内容详细

项目开发基本流程

1.需求分析
2.架构设计
3.分组开发
4.提交测试
5.交付上线

项目流程

仿博客园项目
	核心:文章的增删改查
表分析
	先确定表的数量 再确定表的基础字段 最后确定表的外键字段
    	1.用户表
        2.个人站点表
        3.文章表
        4.文章分类表
        5.文章标签表
        6.点赞点踩表
        7.文章评论表
基础字段分析
	'''下列表字段设计仅供参考 你可以有更多的想法'''
    用户表
    	替换auth_user表并扩展额外的字段
        	电话号码 头像 注册时间
    个人站点表
    	站点名称(jason/lili/kevin)
        站点标题(努力奋斗)
        站点样式(css文件)
    文章表
    	文章标题
        文章简介
        文章内容
        发布时间
    文章分类表
    	分类名称
    文章标签表
    	标签名称
    点赞点踩表:记录哪个用户给哪篇文章点了推荐(赞)还是反对(踩)
    	用户字段(用户主键)>>>:外键字段
        文章字段(文章主键)>>>:外键字段
        点赞点踩
    文章评论表:记录哪个用户给哪篇文章评论了什么内容
    	用户字段(用户主键)>>>:外键字段
        文章字段(文章主键)>>>:外键字段
        评论内容
        评论时间
        外键字段(自关联)>>>:回复评论的评论
        """
        id	user_id  article_id  content parent_id
		1    1      1       哈哈哈   null
		2   2      1        哈你妹   1
		3   3      1        讲文明   2
        """
外键字段
	用户表
    	用户与个人站点是一对一外键关系
        
    个人站点表
    
    文章表
    	文章表与个人站点表是一对多外键关系
        文章表与文章分类表是一对多外键关系
        文章表与文章标签表是多对多外键关系
        '''
        数据库字段优化设计:我们想统计文章的评论数 点赞数
        	通过文章数据跨表查询到文章评论表中对应的数据统计即可
        但是文章需要频繁的展示 每次跨表查询的话效率极低
        	我们在文章表中再创建三个普通字段
        之后只需要确保每次操作评论表或者点赞点踩表时同步修改上述三个普			通字段即可
        '''
        文章评论数
        文章点赞数
        文章点踩数
        
    文章分类表
    	文章分类与个人站点是一对多外键关系
        
    文章标签表
    	文章标签与个人站点是一对多外键字段

'''models代码'''
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.


class UserInfo(AbstractUser):
    """用户表"""
    phone = models.BigIntegerField(verbose_name='手机号', null=True)
    avatar = models.FileField(upload_to='avatar/', default='avatar/default.jpg', verbose_name='用户头像')
    register_time = models.DateTimeField(verbose_name='注册时间', auto_now_add=True)

    site = models.OneToOneField(to='Site', on_delete=models.CASCADE, null=True)


class Site(models.Model):
    """个人站点表"""
    site_name = models.CharField(verbose_name='站点名称', max_length=32)
    site_title = models.CharField(verbose_name='站点标题', max_length=32)
    site_theme = models.CharField(verbose_name='站点样式', max_length=32, null=True)  # 简单模拟样式文件


class Article(models.Model):
    """文章表"""
    title = models.CharField(verbose_name='文章标题', max_length=32)
    desc = models.CharField(verbose_name='文章简介', max_length=255)
    content = models.TextField(verbose_name='文章内容')
    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    # 三个优化字段
    comment_num = models.IntegerField(verbose_name='评论数', default=0)
    up_num = models.IntegerField(verbose_name='点赞数', default=0)
    down_num = models.IntegerField(verbose_name='评论数', default=0)\

    site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)
    category = models.ForeignKey(to='Category', on_delete=models.CASCADE, null=True)
    tags = models.ManyToManyField(to='Tag',
                                  through='Article2Tag',
                                  through_fields=('article', 'tag'),
                                  null=True
                                  )


class Category(models.Model):
    """文章分类表"""
    name = models.CharField(verbose_name='分类名称', max_length=32)
    site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)


class Tag(models.Model):
    """文章标签表"""
    name = models.CharField(verbose_name='标签名称', max_length=32)
    site = models.ForeignKey(to='Site', on_delete=models.CASCADE, null=True)


class Article2Tag(models.Model):
    """文章和文章标签的多对多第三张表"""
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE, null=True)
    tag = models.ForeignKey(to='Tag', on_delete=models.CASCADE, null=True)


class UpAndDown(models.Model):
    """文章点赞点踩表"""
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE, null=True)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE, null=True)
    is_up = models.BooleanField(verbose_name='点赞点踩')  # 布尔值存储,0或者1


class Comment(models.Model):
    """文章评论表"""
    user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE, null=True)
    article = models.ForeignKey(to='Article', on_delete=models.CASCADE, null=True)
    content = models.TextField(verbose_name='评论内容')
    comment_time = models.DateTimeField(auto_now_add=True, verbose_name='评论时间')
    parent = models.ForeignKey(to='self', on_delete=models.CASCADE, null=True)

注册功能

用户注册
	1.渲染前端标签
    2.校验用户数据
    3.展示错误提示
ps:forms组件,modelform组件

单独开设py文件编写 解耦合!!!
单独开设一个py文件编写forms类
from django import forms
from app01 import models


class RegisterForm(forms.Form):
    """用户注册form类"""
    username = forms.CharField(min_length=3, max_length=8, label='用户名',
                               error_messages={
                                   'min_length': '用户名最短三位',
                                   'max_length': '用户名最长八位',
                                   'required': '用户名不能为空',
                               },
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
                               )
    password = forms.CharField(min_length=3, max_length=8, label='密码',
                               error_messages={
                                   'min_length': '密码最短三位',
                                   'max_length': '密码最长八位',
                                   'required': '密码不能为空',
                               },
                               widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                               )
    confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
                               error_messages={
                                   'min_length': '密码最短三位',
                                   'max_length': '密码最长八位',
                                   'required': '密码不能为空',
                               },
                               widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                               )
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'required': '邮箱不能为空',
                                 'invalid': '邮箱格式不正确'
                             },
                             widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                             )
    # 用户头像单独校验 不使用校验类

    # 钩子函数
    # 局部钩子校验用户名是否已存在
    def clean_username(self):
        username = self.cleaned_data.get('username')
        res = models.UserInfo.objects.filter(username=username)
        if res:
            self.add_error('username', '用户名已存在')
        return username

    # 全局钩子校验两次密码是否一致
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password', '两次密码不一致')
        return self.cleaned_data

前端代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户注册页面</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.css' %}">
    <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</head>
<body>
    <div class="container">
        <div class="col-md-8 col-md-offset-2">
            <h2 class="text-center">用户注册</h2>
            <form id="form">  <!--不使用form表单提交数据 但是用一下form标签 它有一个序列化功能-->
                {% csrf_token %}
                {% for form in form_obj %}
                    <div class="form-group">  <!--目的是让多个获取用户数据的标签上下间距更大一些-->
                        <label for="{{ form.auto_id }}">{{ form.label }}</label>  <!--form.auto_id自动获取渲染的标签id值-->
                        {{ form }}
                        <span style="color: red" class="pull-right">{{ form.errors.0 }}</span>
                    </div>
                {% endfor %}
                <!--用户头像自己编写相关标签获取-->
                <div class="form-group">
                    <label for="myfile">
                        头像<img src="/static/img/default.jpg" alt="" width="100" id="myimg">
                    </label>
                    <input type="file" id="myfile" style="display: none">

                </div>
                <input type="button" id="subBtn" class="btn btn-primary btn-block" value="注册">
            </form>

        </div>
    </div>
    <script>
        // 1.用户头像的实时展示
        $('#myfile').change(function () {
            // 1.产生一个文件阅读对象
            let myFileReaderObj = new FileReader();
            // 2.获取用户上传的头像文件
            let fileObj = this.files[0];
            // 3.将文件对象交给阅读对象读取
            myFileReaderObj.readAsDataURL(fileObj);  // 异步操作
            // 等待文件阅读器对象加载完毕之后再修改src
            myFileReaderObj.onload = function () {
                // 4.修改img标签的src属性展示图片
                $('#myimg').attr('src', myFileReaderObj.result)
            }

        })
        
        // 2.给注册按钮绑定点击事件 发送ajax
        $('#subBtn').click(function () {
            // 1.先产生一个内置对象
            let myFormDateObj = new FormData();
            // 2.添加普通数据
            {#myFormDateObj.append()#}
            {#console.log($('#form').serializeArray())  // 可以一次性获取form标签内所有的普通字段数据#} // [{},{},{},{}]
            $.each($('#form').serializeArray(), function (index, dataObj) {  // 对结果for循环 然后交给后面的函数处理
                myFormDateObj.append(dataObj.name, dataObj.value)  // {'name':'', 'value':''}
            })
            // 3.添加文件数据
            myFormDateObj.append('avatar', $('#myfile')[0].files[0])
            // 4.发送ajax请求
            $.ajax({
                url:'',
                type:'post',
                data:myFormDateObj,

                contentType:false,
                processData: false,

                success:function (args) {
                    if(args.code === 10000){
                        window.location.href = args.url
                    }else {
                        {#console.log(args.msg)#}
                        let dataObj = args.msg;
                        // 如何针对性的渲染错误提示 {'username'} id_username
                        $.each(dataObj, function (k, msgArray) {
                            // 拼接标签的id值
                            let eleId = '#id_' + k
                            // 根据id查找标签 修改下面span标签的内容 并给父标签添加错误样式
                            $(eleId).next().text(msgArray[0]).parents().addClass('has-error')
                        })

                    }
                }
            })
        })

        // 3.给所有的input标签绑定焦点事件 移除错误样式
        $('input').focus(function () {
            $(this).next().text('').parents().removeClass('has-error')
        })

    </script>
</body>
</html>

view视图注册函数编写
from django.shortcuts import render, HttpResponse, redirect
from app01 import myforms
from app01 import models
from django.http import JsonResponse
# Create your views here.


def register_func(request):
    # 前后端ajax交互 通常采用字段作为交互对象
    back_dict = {'code': 10000, 'msg': ''}
    # 1.先产生一个空的form_obj
    form_obj = myforms.RegisterForm()
    # 根据post请求获取数据
    if request.method == 'POST':
        form_obj = myforms.RegisterForm(request.POST)  # username password confirm_password email csrfmiddlewaretoken
        if form_obj.is_valid():
            clean_data = form_obj.cleaned_data  # 存储符合校验的数据 {username password confirm_password email}
            # 将confirm_password移除
            clean_data.pop('confirm_password')  # {username password email}
            # 获取用户上传的头像文件
            avatar_obj = request.FILES.get('avatar')  # 用户可能没有上传
            if avatar_obj:
                clean_data['avatar'] = avatar_obj  # {username password email avatar}
            # 创建用户数据
            models.UserInfo.objects.create_user(**clean_data)  # 上述一大串处理字段的目的就是为了创建数据省事
            back_dict['msg'] = '注册成功'
            back_dict['url'] = '/login/'
        else:
            back_dict['code'] = 10001
            back_dict['msg'] = form_obj.errors
        return JsonResponse(back_dict)
    return render(request, 'registerPage.html', locals())

登录功能

img标签的src属性
	1.可以直接填写图片验证
    2.还可以填写一个路由 会自动朝该路由发送get请求
    如果结果是图片的二进制数据 那么自动渲染图片

后端代码
def login_func(request):
    return render(request, 'loginPage.html')


from PIL import Image, ImageFont, ImageDraw
"""
Image           产生图片
ImageFont       字体样式
ImageDraw       画笔对象
"""
from io import BytesIO, StringIO
"""
BytesIO         在内存中临时存储数据 读取时以bytes格式为准
StringIO        在内存中临时存储数据 读取时以字符串格式为准
"""
import random


def get_random():
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)


def get_code_func(request):
    # 1.推导步骤1:直接读取图片文件返回
    # with open(r'F:\APP\pycharm\pythonProject\BBS01\avatar\111.jpeg', 'rb') as f:
    #     data = f.read()
    # return HttpResponse(data)
    # 2.推导步骤2:随机产生图片动态返回 第三方模块pillow
    # img_obj = Image.new('RGB', (350, 35), 'red')
    # with open(r'xxx.png', 'wb')as f:
    #     img_obj.save(f, 'png')
    # with open(r'xxx.png', 'rb')as f:
    #     data = f.read()
    # return HttpResponse(data)
    # 3.推导步骤3:针对图片的保存与读取作优化 内存管理器
    # img_obj = Image.new('RGB', (350, 35), 'yellow')
    # io_obj = BytesIO()
    # img_obj.save(io_obj, 'png')
    # return HttpResponse(io_obj.getvalue())
    # 4.推导步骤4:图片颜色是可以随机变化的
    img_obj = Image.new('RGB', (350, 35), get_random())
    io_obj = BytesIO()
    img_obj.save(io_obj, 'png')
    return HttpResponse(io_obj.getvalue())
前端代码
    <div class="container">
        <div class="col-md-8 col-md-offset-2">
            <h2 class="text-center">用户登录</h2>
            <div class="form-group">
                <label for="name">用户名</label>
                <input type="text" id="name" class="form-control">
            </div>
            <div class="form-group">
                <label for="password">用户名</label>
                <input type="password" id="password" class="form-control">
            </div>
            <div class="form-group">
                <label for="code">验证码</label>
                <div class="row">
                    <div class="col-md-6">
                        <input type="text" id="code" class="form-control">
                    </div>
                    <div class="col-md-6">
                        <img src="/get_code/" alt="" width="350" height="35">
                    </div>
                </div>
            </div>
            <input type="button" class="btn btn-success btn-block" value="登录">
        </div>
    </div>

标签:obj,name,登录,models,length,form,注册,文章,bbs
From: https://www.cnblogs.com/zpf1107/p/17020766.html

相关文章

  • BBS(仿博客园项目)
    BBS(仿造博客园项目)项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试5.交付上线项目流程仿造博客园项目 核心:文章的增删改查表分析 先确定表的数量......
  • BBS项目
    目录BBS项目开发基本流程项目分析(表)项目注册功能项目登录功能项目实操注册功能登录功能BBS项目开发基本流程需求分析架构设计分组开发提交测试交付上线项目分析(......
  • bbs
    项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试5.交付上线项目流程仿造博客园项目 核心:文章的增删改查表分析 先确定表的数量再确定表的基础字段......
  • bbs项目
    内容概要主题:仿BBS项目项目开发基本流程项目分析(表)项目注册功能项目登录功能今日内容详细项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试......
  • BBS仿博客园
    目录项目开发基本流程一、BBS表设计1.表字段设计1.用户表2.个人站点表3.文章标签表4.文章分类表5.文章表6.点赞点踩表7.文章评论表2.七章表之间的关系1.用户表和个人站点表......
  • django_BBS博客系统练习
    表设计表分析先确认表的数量再确认表的基础字段最后确认表的外键字段1.用户表(基于auth模块设计扩展,手机号,头像,注册时间)fromdjango.contrib.auth.modelsimportAbst......
  • BBS项目 前期准备及注册、登录部分
    项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试5.交付上线创建项目配置环境配置TEMPLATES=[{'BACKEND':'django.template.backends......
  • BBS项目练习
    BBS项目练习此项目是对博客园软件的简单模仿,旨在整合django的知识点。七张信息表用户表(与站点一对一)站点表文章表(与站点一对多)文章分类表文章标签表点赞点踩表......
  • Spring Security 源码分析(四):Spring Social实现微信社交登录
    前言在上一章Spring-Security源码分析三-Spring-Social社交登录过程中,我们已经实现了使用​​SpringSocial​​​+​​Security​​的QQ社交登录。本章我们将实现微信的社......
  • BBS项目
    项目开发基本流程1.需求分析2.架构设计3.分组开发4.提交测试5.交付上线项目流程仿博客园项目 核心:文章的增删改查表分析 先确定表的数量,在确定表的基础字段,最......