zoukankan      html  css  js  c++  java
  • DAY87-BBS项目(一) 数据库设计与简单登陆、验证码

    一、BBS项目之项目分析

    项目流程:
    
    1 搞清楚需求(产品经理)
    
      (1) 基于用户认证组件和Ajax实现登录验证(图片验证码)
    
      (2) 基于forms组件和Ajax实现注册功能
    
      (3) 设计系统首页(文章列表渲染)
    
      (4) 设计个人站点页面---跨表查询,分组查询
    
      (5) 文章详情页
    
      (6) 实现文章点赞功能
    
      (7) 实现文章的评论
          ---文章的评论
          ---评论的评论
    
      (8) 副文本编辑框 和 防止xss攻击(防止别人提交js代码)
    
    
    2 设计表结构
    
    
    3 按着每一个功能分别进行开发
      
    
    4 功能测试
    
    
    5 项目部署上线
    

    二、数据库设计

    1.分析数据表以及表关系

    用户表:UserInfo
    个人站点表:blog
    文章表:Article
    评论表:commit
    点赞点踩表:upanddown
    文章分类表:category
    文章标签表:tag
    

    2.设计字段

    User:继承AbstractUser,用户表
    	nid
    	phone
    	avatar   用户头像
    	blog
    Blog:站点
    	nid
    	title
    	site_name
    	theme
    category:分类
    	nid
    	title
    	blog   跟blog一对多
    tag:(文章关键字)
    	nid
    	title
    	blog    跟blog一对多
    
    article:文章
    	nid
    	title
    	desc    摘要
    	create_time    auto_add_now:当该条记录创建时,自动添加当前时间
    	content   文章内容
    	category    一对多
    	blog        一对多
    	tag         多对多
    
    commit:评论
    	nid
    	user     哪个用户
    	article  对哪篇文章
    	content   评论了什么内容
    	commit_time  时间
    	parent_id	子评论
    	
    UpAndDown:点赞
    	nid
    	user
    	article
    	is_up
    

    3.创建数据库

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    
    # Create your models here.
    
    class UserInfo(AbstractUser):
        nid = models.AutoField(primary_key=True)
        # 电话可以为空
        phone = models.CharField(max_length=32, null=True)
        # 头像
        avatar = models.FileField(upload_to='avatar/', default='/static/image/default.png')
        # 站点
        blog = models.OneToOneField(to='Blog', to_field='nid')
    
        # 用户和用户的站点应该是联合唯一的
        class Mate:
            unique_together = (('username', 'blog'),)
    
    
    class Blog(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=64)
        # 站点路径
        site_name = models.CharField(max_length=32)
        # 主题
        theme = models.CharField(max_length=64)
    
    
    # 分类
    class Category(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=64)
        # 个人站点可以拥有多个分类
        blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
    
    
    # 标签
    class Tag(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=64)
        # 个人站点可以拥有多个标签
        blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
    
    
    # 文章
    class Article(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=64)
        # 文章简介
        desc = models.CharField(max_length=255)
        # 文章内容
        content = models.TextField()
        # 创建时间
        create_time = models.DateTimeField(auto_now_add=True)
        # 个人站点可以拥有多篇文章
        blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
        # 一个分类可以拥有多篇文章
        category = models.ForeignKey(to='Category', to_field='nid', null=True)
        # 文章和标签是多对多的关系,一篇文章可以由多个标签,一个标签可以给多篇文章使用
        # 手动创建第三张表
        tag = models.ManyToManyField(to='Tag', through='Article2Tag', through_fields=('article', 'tag'))
    
    
    # 多对多第三张表
    class Article2Tag(models.Model):
        nid = models.AutoField(primary_key=True)
        tag = models.ForeignKey(to='Tag', to_field='nid')
        article = models.ForeignKey(to='Article', to_field='nid')
    
        class Mate:
            unique_together = (('tag', 'article'),)
    
    
    # 评论
    class Commit(models.Model):
        nid = models.AutoField(primary_key=True)
        # 评论内容
        content = models.TextField()
        # 评论时间
        create_time = models.DateTimeField(auto_now_add=True)
        # 可以对评论作出评论,设置一个字段用来表示是对哪条评论做出的评论
        # 方法1
        # parent_id = models.ForeignKey(to='Commit',to_field='nid')
        # 方法2
        parent_id = models.ForeignKey(to='self',to_field='nid')
        # 一个用户可以评论多条
        user = models.ForeignKey(to='UserInfo', to_field='nid')
        # 一篇文章可以有多条评论
        article = models.ForeignKey(to='Article', to_field='nid')
    
    
    # 点赞
    class UpAndDown(models.Model):
        nid = models.AutoField(primary_key=True)
        # 一个用户可以给多篇文章点赞或踩一下
        user = models.ForeignKey(to='UserInfo', to_field='nid')
        # 一篇文章可以有多个赞和踩
        article = models.ForeignKey(to='Article', to_field='nid')
        # 1是赞,0是踩
        is_up = models.BooleanField()
    
        class Meta:
            # 一个用户只能对一篇文章赞或踩,所以要做联合唯一
            unique_together = (('user', 'article'),)
    

    三、项目配置

    setting.py

    #链接数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'bbs',
            'POST': 3306,
            'HOST': '127.0.0.1',
            'USER': 'root',
            'PASSWORD': 'root'
        }
    }
    #静态文件路径配置
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'static')
    ]
    #auth组件authinfo表路径
    AUTH_USER_MODEL = 'blog.UserInfo'
    

    四、登录功能以及验证码

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录</title>
        {% load static %}
        <link rel="stylesheet" href="{% get_static_prefix %}bootstrap-3.3.7-dist/css/bootstrap.css">
        <script src="{% get_static_prefix %}jquery-3.3.1.js"></script>
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-4 col-md-offset-4">
                <h1 style="text-align: center">登录</h1>
                <form>
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="name">用户名</label>
                        <input type="text" class="form-control" id="name" placeholder="用户名" required>
                    </div>
                    <div class="form-group">
                        <label for="pwd">密码</label>
                        <input type="password" class="form-control" id="pwd" placeholder="密码" required>
                    </div>
                    <div class="form-group">
                        <label for="validCode">验证码</label>
                        <div class="row">
                            <div class="col-md-6">
                                <input type="text" class="form-control" id="validCode" placeholder="验证码不分大小写" required>
                            </div>
                            <div class="col-md-6">
                                <img src="/get_validCode/" title="60s后失效" height="35" width="200" class="img-rounded"
                                     id="get_validCode_img">
                            </div>
                        </div>
                    </div>
                </form>
                <button type="button" class="btn btn-primary btn-lg pull-right" id="btn">登录</button>
            </div>
    
        </div>
    </div>
    </body>
    <script>
        $(function () {
            $("#get_validCode_img").click(function () {
                $(this)[0].src += '?'
            })
        });
        $('#btn').click(function () {
    
            var da = {'name':$('#name').val(),'pwd':$('#pwd').val(),'validCode':$('#validCode').val(),csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()}
            $.ajax({
                url:'/login/',
                type:'post',
                data:da,
                success:function (data) {
                    alert(data)
                }
            })
        })
    </script>
    </html>
    

    验证码

    from PIL import Image, ImageDraw, ImageFont
    from BBS import common
    from io import BytesIO
    
    def get_validCode(request):
        # 第一种方式:本地存放固定图片
        # with open('static/1.png','rb') as f:
        #     data = f.read()
        # return HttpResponse(data)
    
        # # 第二种方式:本地存放随机图片
        # # 生成图片 new(模式,宽高,颜色)
        # img = Image.new('RGB', (200, 35),color=common.get_color())
        # # 写一个空白本地图片文件
        # with open('ve_code.png', 'wb') as f:
        #     # 调用img对象的save方法保存到空文件
        #     img.save(f,'png')
        # # 打开文件,再返回
        # with open('ve_code.png','rb') as f:
        #     data = f.read()
        # return HttpResponse(data)
    
        # # 第三种方式:在内存中存放随机图片
        # # 生成图片 new(模式,宽高,颜色)
        # img = Image.new('RGB', (200, 35),color=common.get_color())
        # # 生成一个空白内存文件
        # f = BytesIO()
        # # 调用img对象的save方法保存到空内存文件
        # img.save(f,'png')
        # # 获取内存文件的内容
        # data = f.getvalue()
        # return HttpResponse(data)
    
        # 第四种方式:在内存中存放随机图片,在图片上加上随机验证码
        # 生成图片对象 new(模式,宽高,颜色)
        img = Image.new('RGB', (200, 35), color=common.get_color())
        # 生成画笔对象,并将图片对象传入
        img_draw = ImageDraw.Draw(img)
        # 生成字体对象
        font = ImageFont.truetype('static/font/ss.ttf', size=25)
        # 将文字用画笔写入图片
        # text(坐标,文字,颜色,字体)
        img_draw.text((50, 0), common.get_ve_code(request), common.get_color(), font)
        # 生成一个空白内存文件
        f = BytesIO()
        img.save(f, 'png')
        data = f.getvalue()
        return HttpResponse(data)
    

    共用模块

    import random
    
    # 产生随机RGB
    def get_color():
        return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    
    # 产生随机验证码
    def get_ve_code(request):
        ve_code = ''
        for i in range(5):
            number = random.randint(0, 9)
            upper = chr(random.randint(97, 122))
            lower = chr(random.randint(65, 90))
            add = random.choice((number, upper, lower))
            ve_code += str(add)
        request.session['ve_code']=ve_code
        request.session.set_expiry(60)
        return ve_code
    

    登录

    from django.shortcuts import render, HttpResponse
    from django.contrib import auth
    
    
    # Create your views here.
    def login(request):
        if request.method == 'GET':
            return render(request, 'login.html')
        else:
            name = request.POST.get('name')
            pwd = request.POST.get('pwd')
            validCode = request.POST.get('validCode')
            user = auth.authenticate(username=name, password=pwd)
            validCode_sess = request.session.get('ve_code')
            if validCode.upper() != validCode_sess.upper():
                return HttpResponse('验证码错误')
            if user is not None:
                return HttpResponse('登陆成功')
            else:
                return HttpResponse('用户名或密码错误')
    
  • 相关阅读:
    集成学习
    逻辑斯谛回归
    【腾讯】【实习】【笔试】【数据分析师】2018.04.05
    C语言中scanf和printf的用法详解
    寻找一个数组中未出现的最小正整数(数组元素可重复)
    吃鸡问题中的的动态规划
    Coursera 深度学习 吴恩达 deep learning.ai 第三课 结构化机器学习项目 第二周 测试题目 Autonomous driving (case study)
    【转】P问题与NP问题详细解答加举例
    LeetCode 149. Max Points on a Line
    LeetCode 150. Evaluate Reverse Polish Notation
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/10028392.html
Copyright © 2011-2022 走看看