一、BBS-个人博客项目完整搭建
项目开发流程
一、项目分类
现在互联网公司需要开发的主流web项目一般分为两类:面向互联网用户,和公司内部管理。
面向互联网用户: C(consumer)端项目
公司内部管理:B(business)端项目
还有一类web应用,基本采用基于角色的权限控制,不同的员工在这套系统中拥有不同的权限,
适用于公司内部管理。
基于权限的后台关系系统:
RBAC权限管理系统
二、项目开发模式分类
最常见的两类为瀑布开发模式和敏捷开发模式。
1、瀑布开发模式
瀑布开发模式是一种更倾向于严格控制的管理模式,要求在提出需求之后,充分完成项目的规划,各阶段都要经过严格的评审,只有当一个阶段的需求完成得非常好时才能进入下一个阶段。
但是瀑布开发模式开发的失败率较高,且周期较长,于是就产生了敏捷开发模式。
2、敏捷开发模式
敏捷开发模式的核心是迭代开发,它将一个项目完整的开发流程分为了几个周期(也可以说是版本),由于每个版本的开发流程相似,看上去相当于一个重复迭代的过程。这么开发的好处是,使一个大的项目能在较短时间内上线,并在后续对它进行不断地迭代和优化。
3、项目开发流程
-立项
-需求分析
-原型图(产品画的)
-切图
-技术选型,数据库架构设计
-前后端协同开发
-上线测试服务器联调
-测试
-修改bug
-上线运行
二、BBS多人博客项目基本功能和需求
比如:产品需求的确定,技术选型,数据库设计...
"""
1. 用户表(你可以自己创建,也可以使用auth_user表)
扩展auth_user表
phone
avatar:用来存储头像的地址
create_time:用户注册的时间
...
blog_id = OneToOneField(to='blog')
2. 站点表(blog)
站点名称
站点标题
站点样式:存的是css的路径
3. 分类表(cate)
分类名称
blog = ForeignKey(to='blog')
4. 标签表
标签名称
blog = ForeignKey(to='blog')
5. 文章表(*******************article)
文章标题
文章摘要
文章内容
文章发表时间
# 1. 通过文章id去点赞表或者评论表中查询
# 优化
# 2. 在文章表中增加子弹
up_num 1
down_num 1
comment_num 4
# 外键关系子弹
cate = ForeignKey(to='cate')
tag = ManyToManyField(to='tag')
blog = ForeignKey(to='blog')
6. 点赞点踩表
谁给哪篇文章什么时间点了赞还是踩
user ForeignKey(to='user')
article ForeignKey(to='article')
is_up 0/1
create_time
id user_id article_id is_up create_time
1 1 1 0 ‘’
2 2 1 1 ‘’
7. 评论表(comment)
谁给哪篇文章在什么时间评论了什么内容
user ForeignKey(to='user')
article ForeignKey(to='article')
content
create_time
parent_id ForeignKey(to='comment')
parent_id ForeignKey(to='self')
#自关联
id user_id article_id content create_time parent_id
1 1 1 0 ‘’ 0
2 2 1 1 ‘’ 1
3 2 1 1 ‘’ 2
子评论!!!
评论评论的评论!!!
根评论
1. Python是世界上最好的语言
1.1 PHP是世界上最好的语言
1.2 Java是世界上最好的语言
无限极分类
category表
id cate_name pid
1 手机/数码 0
2 电脑/办公 0
...
20 手机通讯 1
21 运营商 1
...
50 5G手机 20
51 手机 20
...
100 128G/5G 50
"""
三、项目程序设计
四、BBS数据库表结构设计
1.用户表:UserInfo
(通过继承AbstractUser类来扩写Auth_user)
•phone:用户的联系方式
•bg_img: 用户的主页背景
•province: 用户的省份
•city: 用户的城市
•gender : 用户的性别
•avatar:用户的头像
•blog:用户的博客站点(外键一对一关联博客表Blog)
2.博客表:Blog
•title:博客标题
•subtitle: 博客子标题
•style:博客样式
3.文章表:Article
•title:文章标题
•head_img: 头像
•description:文章摘要
•content:文章内容
•create_time:文章的创建时间
•modify_time: 文章的修改时间
•up_num :点赞数
•down_num:点踩数
•comment_num:评论数
•blog:属于哪个博客站点(外键关联博客表Blog)
•category:属于哪个分类(外键关联分类表Category)
4.标签表:Tag
•name:标签名
•blog:属于哪个博客站点(外键关联博客表Blog)
5.分类表:Category
•name:分类名
•blog:属于哪个博客站点(外键关联博客表Blog)
6.评论表:Comment
•user:评论的用户(外键关联用户表UserInfo)
•article:该评论属于哪篇文章(外键关联文章表Article)
•content:评论内容
•comment_time: 评论的创建时间
•comment_id:评论的目标id(外键进行自关联)
7.点赞点踩表:UpAndDown
•user:来自哪个用户(外键关联用户表UserInfo)
•article:属于哪篇文章(外键关联文章表Article)
•is_up:点赞还是点踩(根据bool值来判断)
•create_time : 点赞或踩的时间
8.文章标签表: Tag2Article
根据文章与标签的多对多关系手动建立的第三张表
• tag:标签名(外键关联标签表Tag)
• article:属于哪篇文章(外键关联文章表Article)
9.轮播图表 Swiper (拓展)
• image: 轮播图图片名
• title:轮播图标题
• img_url: 点击轮播图要跳转的url地址
10.日志表: Log(拓展)
• id: 日志id
• ip: 访问的ip地址
• time: 访问的时间
• url: 访问的url
• device: 访问的浏览器
• platform:访问的操作系统类型
11.日志表: Log(拓展)
• id: 日志id
• ip: 访问的ip地址
• time: 访问的时间
• url: 访问的url
• device: 访问的浏览器
• platform:访问的操作系统类型
五、创建BBS表模型
模型层models.py中写入以下orm语句模型来创建表模型
from django.contrib.auth.models import AbstractUser
from django.utils.html import mark_safe
from django.db import models
from markdown import markdown
class Log(models.Model):
id = models.AutoField(primary_key=True)
ip = models.CharField(max_length=64, verbose_name='访问IP', help_text='访问用户的IP地址')
time = models.DateTimeField(auto_now_add=True, verbose_name='访问时间', help_text='该用户的访问时刻')
url = models.CharField(max_length=64, verbose_name='访问的URL', help_text='该用户访问的URL地址')
device = models.CharField(max_length=256, null=True, verbose_name='访问的浏览器', help_text='该用户是用什么浏览器访问的')
platform = models.CharField(max_length=256, null=True, verbose_name='访问的系统', help_text='该用户用的是什么操作系统')
def __str__(self):
return self.ip
class Meta:
ordering = ['id']
verbose_name_plural = '日志'
class UserInfo(AbstractUser):
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png', verbose_name='头像', help_text='该用户的头像')
bg_img = models.FileField(upload_to='bg_img/', default='bg_img/default_bg.png', verbose_name='头像',
help_text='该用户的主页背景')
province = models.CharField(max_length=32, default='', verbose_name='省', help_text='该用户的省')
city = models.CharField(max_length=32, default='', verbose_name='城市', help_text='该用户的市')
gender = models.IntegerField(choices=((0, '保密'), (1, '男'), (2, '女')), default=0, verbose_name='性别',
help_text='该用户的性别')
phone = models.CharField(max_length=11, null=True, default='', verbose_name='联系方式', help_text='该用户的联系方式')
blog = models.OneToOneField(to='Blog', on_delete=models.CASCADE, null=True, verbose_name='博客', help_text='该用户的博客')
def __str__(self):
return self.username
class Meta:
verbose_name_plural = '用户'
class Blog(models.Model):
title = models.CharField(max_length=32, verbose_name='博主昵称', help_text='博主昵称')
subtitle = models.CharField(max_length=32, verbose_name='子标题/公告', help_text='博客的子标题/公告')
style = models.CharField(max_length=32, verbose_name='样式', help_text='该博客独有的样式')
def __str__(self):
return self.title
class Meta:
verbose_name_plural = '博客站点'
class Article(models.Model):
title = models.CharField(max_length=32, verbose_name='标题', help_text='文章的标题')
head_img = models.FileField(upload_to='article_head_img/', default='article_head_img/default_head.png',
verbose_name='头图',
help_text='文章的头图')
description = models.CharField(max_length=128, verbose_name='摘要', help_text='简要描述该文章')
content = models.TextField(verbose_name='内容', help_text='文章的内容')
markdown = models.TextField(verbose_name='Markdown内容', default='暂无', help_text='文章的Markdown内容')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='该文章的创建时间')
modify_time = models.DateTimeField(auto_now=True, verbose_name='修改时间', help_text='该文章的最后修改时间')
up_num = models.IntegerField(default=0, verbose_name='点赞数', help_text='该文章的点赞数')
down_num = models.IntegerField(default=0, verbose_name='点踩数', help_text='该文章的点踩数')
comment_num = models.IntegerField(default=0, verbose_name='评论数', help_text='该文章的评论数')
blog = models.ForeignKey(to='Blog', on_delete=models.CASCADE, null=True, blank=True, verbose_name='博客',
help_text='该文章属于哪个博客页面')
category = models.ForeignKey(to='Category', on_delete=models.CASCADE, null=True, blank=True, verbose_name='分类',
help_text='该文章属于哪个分类')
tag = models.ManyToManyField(to='Tag', through='Tag2Article',
through_fields=('article', 'tag'), verbose_name='标签',
help_text='该文章有哪些标签')
def get_text_md(self):
return mark_safe(markdown(self.content))
def __str__(self):
return self.title
class Meta:
verbose_name_plural = '文章'
ordering = ['id', ]
class Tag(models.Model):
name = models.CharField(max_length=32, verbose_name='标签', help_text='标签的名字')
blog = models.ForeignKey(to='Blog', on_delete=models.DO_NOTHING, null=True, blank=True, verbose_name='博客',
help_text='该标签属于哪个博客页面')
def __str__(self):
return self.name
class Meta:
verbose_name_plural = '标签'
class Category(models.Model):
name = models.CharField(max_length=32, verbose_name='分类', help_text='分类的名称')
blog = models.ForeignKey(to='Blog', on_delete=models.DO_NOTHING, null=True, blank=True, verbose_name='博客',
help_text='该分类属于哪个博客页面')
def __str__(self):
return self.name
class Meta:
verbose_name_plural = '分类'
class Comment(models.Model):
user = models.ForeignKey(to='UserInfo', on_delete=models.DO_NOTHING, verbose_name='用户', help_text='该评论来自哪个用户')
article = models.ForeignKey(to='Article', on_delete=models.CASCADE, null=True, verbose_name='文章',
help_text='评论的对象是哪篇文章')
content = models.CharField(max_length=256, verbose_name='内容', help_text='评论的内容')
comment_time = models.DateTimeField(auto_now_add=True, verbose_name='时间', help_text='评论的时间')
comment_id = models.ForeignKey(to='self', on_delete=models.CASCADE, null=True, verbose_name='评论id',
help_text='对哪个id的评论进行评论')
def __str__(self):
return self.content
class Meta:
verbose_name_plural = '评论'
class UpAndDown(models.Model):
user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE, verbose_name='用户', help_text='来自哪个用户')
article = models.ForeignKey(to='Article', on_delete=models.CASCADE, null=True, verbose_name='文章',
help_text='针对哪篇文章')
is_up = models.BooleanField(null=True, verbose_name='点赞点踩', help_text='True为点赞,False为点踩')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='点赞点踩的时间')
def __str__(self):
return self.user
class Meta:
verbose_name_plural = '点赞点踩'
class Tag2Article(models.Model):
tag = models.ForeignKey(to='Tag', on_delete=models.SET_DEFAULT, default='', verbose_name='标签', help_text='关联的标签')
article = models.ForeignKey(to='Article', on_delete=models.CASCADE, default='', verbose_name='文章',
help_text='关联的文章')
class Meta:
verbose_name_plural = '标签关联文章'
class Swiper(models.Model):
image = models.FileField(upload_to='swiper_img/', default='swiper_img/default.jpg', verbose_name='图片',
help_text='轮播图的图片')
title = models.CharField(max_length=32, verbose_name='标题', help_text='图片的标题')
img_url = models.CharField(max_length=64, verbose_name='URL', help_text='点击图片要跳转的URL地址')
def __str__(self):
return self.img_url
class Meta:
verbose_name_plural = '轮播图'
django2表设计
from django.db import models
"""
先写普通字段
之后再写外键字段
"""
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
phone = models.BigIntegerField(verbose_name='手机号', null=True)
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png', verbose_name='用户头像')
"""
给avatar字段传文件对象 该文件会自动存储到avatar文件下 然后avatar字段只保存文件路径avatar/default.png
"""
create_time = models.DateField(auto_now_add=True)
blog = models.OneToOneField(to='Blog', null=True, on_delete=models.CASCADE)
class Blog(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=64)
class Category(models.Model):
name = models.CharField(verbose_name='文章分类', max_length=32)
blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)
class Tag(models.Model):
name = models.CharField(verbose_name='文章标签', max_length=32)
blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)
class Article(models.Model):
title = models.CharField(verbose_name='文章标题', max_length=64)
desc = models.CharField(verbose_name='文章简介', max_length=255)
content = models.TextField(verbose_name='文章内容')
create_time = models.DateField(auto_now_add=True)
up_num = models.IntegerField(verbose_name='点赞数', default=0)
down_num = models.IntegerField(verbose_name='点踩数', default=0)
comment_num = models.IntegerField(verbose_name='评论数', default=0)
blog = models.ForeignKey(to='Blog', null=True, on_delete=models.CASCADE)
category = models.ForeignKey(to='Category', null=True, on_delete=models.CASCADE)
tags = models.ManyToManyField(to='Tag',
through='Article2Tag',
through_fields=('article', 'tag')
)
class Article2Tag(models.Model):
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
tag = models.ForeignKey(to='Tag', on_delete=models.CASCADE)
class UpAndDown(models.Model):
user = models.ForeignKey(to='UserInfo', on_delete=models.CASCADE)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
is_up = models.BooleanField()
class Comment(models.Model):
user = models.ForeignKey(to='UserInfo', null=True, on_delete=models.CASCADE)
article = models.ForeignKey(to='Article', null=True, on_delete=models.CASCADE)
content = models.CharField(verbose_name='评论内容', max_length=255)
comment_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)
parent = models.ForeignKey(to='self', null=True, on_delete=models.CASCADE)