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('用户名或密码错误')

猜你喜欢

转载自www.cnblogs.com/xvchengqi/p/10028392.html
今日推荐