BBS項目涉及的表
# 用戶表 (用戶信息:用戶名、密碼、頭像等)
# 站點表 (博客名、標題、主題等)
# 文章表 (標題、簡介、內容、點贊數評論數等)
# 標簽表 (文章標簽)
# 分類表 (文章分類)
# 點贊表 (哪個用戶給哪篇文章點贊還是點踩)
# 評論表 (哪個用戶給哪篇評論的內容、時間、是否是子評論等)
表設計
用戶表
- 為了使用auth模塊的功能和auth_user表的已存在字段,需要擴展auth_user表
- 同時用戶表和站點表一對一關聯
標簽表&分類表
- 這兩個表記錄用戶站點的博客需要的標簽和分類,它倆和站點表都是一對多的關系,即一個站點有多個標簽或者分類
點贊表
- 點贊表用於記錄用戶該文章點贊還是點踩,因此該表有個三個字段
- 外鍵關聯用戶表的字段、外鍵關聯文章表的字段、布爾型的字段(是否點贊)
評論表
- 評論表用於記錄用戶該文章的評論內容,因此該表至少有個四個字段
- 外鍵關聯用戶表的字段、外鍵關聯文章表的字段、評論內容和評論時間
- 此外,設計子評論(評論的評論)時,需要再加一個根評論字段關聯自己(該字段可以為空),即自關聯
文章表
- 文章表需要的字段比較多:普通字段就有文章標題、簡介、發布時間、內容等
- 文章需要綁定個人站點、和站點表是一對多的關系,即一個站點有多篇文章(站點用戶也就是文章作者)
- 文章需要分類和標簽、我們自定義文章和分類是一對多的關系,文章和標簽是多對多的關系
- 文章和標簽是多對多的關系,這里使用半自動的方式創建第三張關系表,方便日后擴展。
- 另外創建三個普通字段分別記錄文章點贊數、點踩數、評論數(雖然可以通過跨表查詢獲得這三個數字,但頻繁的跨表查詢效率較低,這是優化數據庫查詢的一種方式;不過此時注意:需要手動同步更新文章表和點贊表或評論表)
補充:表結構設計時先考慮普通字段再考慮外鍵關聯字段
表結構
代碼實現
- 擴展
auth_user
表需要在配置文件配置參數且只能新增額外的字段,不能修改auth_user
表中已經存在的字段。
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
# 擴展auth_user表
phone = models.BigIntegerField(verbose_name='手機號', null=True)
avatar = models.FileField(upload_to='avatar/', default='avatar/default.png')
register_time = models.DateTimeField(auto_now_add=True, verbose_name='注冊時間')
blog = models.OneToOneField(to='Blog', null=True) # 此處null為了方便項目初期數據的添加
def __str__(self):
return self.username
class Meta:
verbose_name_plural = '用戶表' # 該參數用於設置admin后台管理系統中表名稱
class Blog(models.Model):
blog_name = models.CharField(max_length=32, verbose_name='個人站點名')
blog_title = models.CharField(max_length=128, verbose_name='站點標題')
blog_theme = models.CharField(max_length=64, verbose_name='站點樣式')
def __str__(self):
return self.blog_name
class Tag(models.Model):
name = models.CharField(max_length=32, verbose_name='標簽名')
blog = models.ForeignKey(to='Blog', null=True)
def __str__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=32, verbose_name='分類名')
blog = models.ForeignKey(to='Blog', null=True)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=64, verbose_name='標題')
desc = models.CharField(max_length=256, verbose_name='摘要')
content = models.TextField(verbose_name='文章內容')
publish_time = models.DateTimeField(auto_now_add=True)
# 數據庫優化三個字段
up_counts = models.BigIntegerField(verbose_name='點贊數', default=0)
down_counts = models.BigIntegerField(verbose_name='點踩數', default=0)
comment_counts = models.BigIntegerField(verbose_name='評論數', default=0)
blog = models.ForeignKey(to='Blog', null=True)
category = models.ForeignKey(to='Category', null=True)
tags = models.ManyToManyField(to='Tag',
through='Article2Tag', # 半自動創建第三種關系表
through_fields=('article', 'tag') # 字段順序:'先自己后別人';這兩個字段是表Article2Tag中的兩個外鍵字段
)
def __str__(self):
return self.title
class Article2Tag(models.Model):
article = models.ForeignKey(to='Article')
tag = models.ForeignKey(to='Tag')
class UpDown(models.Model):
user = models.ForeignKey(to='UserInfo')
article = models.ForeignKey(to='Article')
is_up = models.BooleanField()
class Comment(models.Model):
user = models.ForeignKey(to='UserInfo')
article = models.ForeignKey(to='Article')
content = models.CharField(max_length=256, verbose_name='評論內容')
comment_time = models.DateTimeField(auto_now_add=True, null=True, verbose_name='評論時間')
parent = models.ForeignKey(to='self', null=True) # 此處自關聯,推薦使用'self'