【引入】BBS表设计
- 一个项目最最最重要的不是业务逻辑的书写
- 而是前期的表设计,只要将表设计好,后续的功能就会相对顺利一些
【1】用户表(User)
字段名 | 类型 | 注释 |
---|
phone | BigIntegerField | 电话 |
avatar | FileField | 头像链接 |
create_time | DateField | 创建时间 |
update_time | DateTimeField | 信息更新时间 |
is_deleted | DateTimeField | 是够被删除(注销) |
blog | OneToOneField | 外键字段,一对一,个人站点表 |
【2】个人站点表(Blog)
字段名 | 类型 | 注释 |
---|
site_name | CharField | 站点名称 |
site_title | CharField | 站点标题 |
site_theme | CharField | 站点样式 |
create_time | DateField | 创建时间 |
update_time | DateTimeField | 信息更新时间 |
【3】广告信息表(Adv)
字段名 | 类型 | 注释 |
---|
title | CharField | 广告标题 |
content | CharField | 广告详细内容 |
mobile | CharField | 广告联系手机号 |
create_time | DateField | 创建时间 |
update_time | DateTimeField | 信息更新时间 |
img | ImageField | 广告投放图片 |
【4】文章分类表(CategoryCls)
字段名 | 类型 | 注释 |
---|
name | CharField | 分类名 |
blog | ForeignKey | 外键字段,一对多,分类关联站点 |
【4】文章标签表(CategoryTag)
字段名 | 类型 | 注释 |
---|
tag_name | CharField | 标签名 |
blog | ForeignKey | 标签关联博客 |
【5】文章表(Article)
字段名 | 类型 | 注释 |
---|
title | CharField | 文章标题 |
desc | CharField | 文章摘要/文章简介 |
content | TextField | 文章内容 |
create_time | DateField | 发布时间 |
update_time | DateField | 更新时间 |
up_num | BigIntegerField | 点赞数 |
down_num | BigIntegerField | 点踩数 |
comment_num | BigIntegerField | 评论数 |
blog | ForeignKey | 外键字段,一对多,文章关联站点 |
category | ForeignKey | 外键字段,多对多,文章关联标签 |
tags | ManyToManyField | 外键字段,一对多,文章关联分类 |
-
数据库字段设计优化
- 虽然点赞数、点踩数和评论数都能从单独的表中查询得出
- 但是频繁地跨表查询效率很低
-
在上表内增加普通字段记录相关的数据
【6】点赞点踩表(UpAndDown)
字段名 | 类型 | 注释 |
---|
user | ForeignKey | 互动关联个人 |
article | ForeignKey | 互动关联文章 |
up_or_down | BooleanField() | 点赞/点踩,1为点赞 |
create_time | DateField | 创建时间 |
update_time | DateTimeField | 信息更新时间 |
字段名 | 类型 | 注释 |
---|
user | ForeignKey | 评论关联个人 |
article | ForeignKey | 评论关联文章 |
content | CharField | 评论详细内容 |
parent | ForeignKey | 自关联 |
create_time | DateField | 创建时间 |
update_time | DateTimeField | 信息更新时间 |
is_deleted | BooleanField | 评论是否被删除,1为存在 |
- 根评论
- 子评论
- 跟评论可以有多个子评论(一对多关系)
# ORM 自带的自关联 写法
ForeignKey(to="self",null=True)
【8】表结构图解
![表结构图解](imgs/%E3%80%90%E5%BC%95%E5%85%A5%E3%80%91BBS%E8%A1%A8%E8%AE%BE%E8%AE%A1.assets/%E8%A1%A8%E7%BB%93%E6%9E%84%E5%9B%BE%E8%A7%A3.png)
【9】数据库建表
版本选择
# Django版本 - Django4.x+ 不支持低版本数据库
django 3.2
# 链接数据库
mysqlclient 2.2.0
# 兼容 ImageField 字段
Pillow 10.0.0
# mysql数据库
PyMySQL 1.1.0
配置文件
# 指定默认用户模型表
AUTH_USER_MODEL = 'user.User'
数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bbs_sys_2.0',
'HOST': "127.0.0.1",
"PORT": 3306,
"USER": "root",
"PASSWORD": "1314521",
"CHARSET": "utf8",
}
}
模型类创建
用户表
from django.db import models
# Create your models here.
# Django中自带的用户认证模型
from django.contrib.auth.models import AbstractUser
# 定义用户信息表
class User(AbstractUser):
'''
用户表
继承基础模型:创建时间/更新时间/用户删除标记
'''
mobile = models.CharField(verbose_name="手机号", help_text="手机号", max_length=11,
default="", blank=True)
avatar = models.ImageField(verbose_name="用户头像", help_text="用户头像",
upload_to="avatar/", default="static/img/default.png")
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
is_deleted = models.BooleanField(verbose_name="删除标记", help_text="删除标记", default=False)
# 用户的个人站点展示
blog = models.OneToOneField(verbose_name="用户关联个人站点", to="blog.Blog", on_delete=models.CASCADE, null=True)
class Meta:
db_table = 'user'
verbose_name = '用户表'
verbose_name_plural = verbose_name
个人站点表
# 个人站点表
class Blog(models.Model):
site_name = models.CharField(verbose_name="个人站点名称", help_text="个人站点名称", max_length=32)
site_title = models.CharField(verbose_name="个人站点标题", help_text="个人站点标题", max_length=32)
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
# css/js 文件的存储路径
site_theme = models.CharField(verbose_name="个人站点样式", help_text="个人站点样式", max_length=64)
class Meta:
db_table = 'blog'
verbose_name = '个人站点表'
verbose_name_plural = verbose_name
广告信息表
# 广告信息表
class Adv(models.Model):
title = models.CharField(verbose_name="广告标题", help_text="广告标题", max_length=64)
content = models.TextField(verbose_name="广告详细内容", help_text="广告详细内容")
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
mobile = models.CharField(verbose_name="手机号", help_text="手机号", max_length=11,
default="", blank=True)
img = models.ImageField(verbose_name="广告图片", help_text="广告图片",
upload_to="advImg/", default="")
文章分类表
# 文章分类表
class CategoryCls(models.Model):
name = models.CharField(verbose_name="文章分类名称", max_length=32)
# 文章的分类关联博客
blog = models.ForeignKey(verbose_name="分类关联博客", help_text="分类关联博客",
to="blog.Blog", on_delete=models.CASCADE,
null=True)
class Meta:
verbose_name = '文章分类表'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
文章标签表
# 文章标签表
class CategoryTag(models.Model):
tag_name = models.CharField(verbose_name="文章标签名称", max_length=32)
# 文章的分类关联博客
blog = models.ForeignKey(verbose_name="标签关联博客", help_text="分类关联博客",
to="blog.Blog", on_delete=models.CASCADE,
null=True)
class Meta:
verbose_name = '文章标签表'
verbose_name_plural = verbose_name
def __str__(self):
return self.tag_name
文章表
# 文章表
class Article(models.Model):
title = models.CharField(verbose_name="文章标题", help_text="文章标题", max_length=64)
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
desc = models.CharField(verbose_name="文章简介", help_text="文章简介", max_length=255)
content = models.TextField(verbose_name="文章详细内容", help_text="文章详细内容")
up_num = models.BigIntegerField(verbose_name="点赞数", help_text="点赞数", default=0)
# 文章创建时间 - create_time - BaseModel
# 文章修改更新时间 - update_time - BaseModel
# 文章是否删除 - is_deleted - BaseModel
down_num = models.BigIntegerField(verbose_name="点踩数", help_text="点踩数", default=0)
comment_num = models.BigIntegerField(verbose_name="评论数", help_text="评论数", default=0)
# 文章关联个人站点
blog = models.ForeignKey(verbose_name="文章关联个人", help_text="文章关联个人", to="blog.Blog",
on_delete=models.CASCADE, null=True)
# 文章关联文章标签
category = models.ForeignKey(verbose_name="文章关联标签", help_text="文章关联标签", to="CategoryTag",
on_delete=models.CASCADE, null=True)
# 文章关联文章分类
tags = models.ForeignKey(verbose_name="文章关联分类", help_text="文章关联分类", to="CategoryCls",
on_delete=models.CASCADE, null=True)
class Meta:
verbose_name = "文章表"
verbose_name_plural = verbose_name
def __str__(self):
return self.title
点赞点踩表
# 点赞点踩表
class UpAndDown(models.Model):
# 互动关联个人
user = models.ForeignKey(verbose_name="互动关联个人", help_text="互动关联个人", to="user.User",
on_delete=models.CASCADE)
# 互动关联文章
article = models.ForeignKey(verbose_name="互动关联文章", help_text="互动关联文章", to="Article",
on_delete=models.CASCADE)
# 互动创建时间 - create_time - BaseModel
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
# 点赞还是点踩
up_or_down = models.BooleanField(verbose_name="点赞或点踩", help_text="点赞或点踩,1为赞0为踩")
class Meta:
verbose_name = "互动表"
verbose_name_plural = verbose_name
评论表
# 评论表
class Comment(models.Model):
user = models.ForeignKey(verbose_name="评论绑定个人", help_text="评论绑定个人", to="user.User",
on_delete=models.CASCADE)
article = models.ForeignKey(verbose_name="评论关联文章", help_text="评论关联文章", to="Article", on_delete=models.CASCADE)
content = models.CharField(verbose_name="评论内容", help_text="评论内容", max_length=255)
# 评论创建时间 - create_time - BaseModel
# 评论是否删除 - is_deleted - BaseModel
create_time = models.DateTimeField(verbose_name="创建时间", help_text="创建时间", auto_now=True)
update_time = models.DateTimeField(verbose_name="更新时间", help_text="更新时间", auto_now_add=True)
is_deleted = models.BooleanField(verbose_name="删除标记", help_text="删除标记", default=False)
# 子评论关联自己 - 允许为空
parent = models.ForeignKey(verbose_name="子评论", help_text="子评论", to="self", on_delete=models.CASCADE,
null=True)
class Meta:
verbose_name = "评论表"
verbose_name_plural = verbose_name