(1) 设计表结构
設計表結構(使用mysql):
BBS-Demp/settings.py
1 LANGUAGE_CODE = 'zh-hans' # admin顯示中文
3 TIME_ZONE = 'Asia/Shanghai' # 時區,默認UTC
5 USE_I18N = True
7 USE_L10N = True
9 USE_TZ = False # 時區,默認True
10
12 DATABASES = {
13 'default': {
14 'ENGINE': 'django.db.backends.mysql',
15 'NAME': 'cnblog', # 數據庫名
16 'USER': 'root', # 用戶名
17 'PASSWORD': 'root', #密碼
18 'HOST': '127.0.0.1', #主機ip
19 'PORT': 3306 # 端口
20 }
21 }
22 AUTH_USER_MODEL = 'app01.UserInfo'
BBS_Demo/__init__.py導入pymysql
1 import pymysql 2 3 pymysql.install_as_MySQLdb()
app01/models.py
1 from django.db import models
2 from django.contrib.auth.models import AbstractUser
3
4 # Create your models here.
5 class UserInfo(AbstractUser):
6 """
7 用戶信息
8 """
9 telephone = models.CharField(max_length=11, null=True, unique=True, verbose_name='手機號')
10 avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png', verbose_name='頭像')
11 create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間')
12
13 blog = models.OneToOneField(to='Blog', null=True,on_delete=models.CASCADE)
14
15 def __str__(self):
16 return self.username
17
18
19 class Blog(models.Model):
20 """
21 博客信息表
22 """
23 title = models.CharField(max_length=64, verbose_name='個人博客標題')
24 site_name = models.CharField(max_length=64, verbose_name='站點名稱')
25 theme = models.CharField(max_length=32, verbose_name='博客主題',null=True,blank=True)
26
27 def __str__(self):
28 return self.title
29
30
31 class Category(models.Model):
32 """
33 博主個人文章分類表
34 """
35 title = models.CharField(max_length=32, verbose_name="分類標題")
36 blog = models.ForeignKey(to='Blog', verbose_name='所屬博客',on_delete=models.CASCADE)
37
38 def __str__(self):
39 return self.title
40
41
42 class Tag(models.Model):
43 """
44 博主個人文章標簽表
45 """
46 title = models.CharField(max_length=32, verbose_name='標簽名稱')
47 blog = models.ForeignKey(to='Blog', verbose_name='所屬博客',on_delete=models.CASCADE)
48
49 def __str__(self):
50 return self.title
51
52
53 class Article(models.Model):
54 """
55 博主個人文章表
56 """
57 title = models.CharField(max_length=64, verbose_name='文章標題')
58 desc = models.CharField(max_length=256, verbose_name='文章摘要')
59 create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間')
60 content = models.TextField(verbose_name='文章內容')
61
62 comment_count = models.IntegerField(default=0,verbose_name='文章評論數')
63 up_count = models.IntegerField(default=0,verbose_name='推薦數')
64 down_count = models.IntegerField(default=0,verbose_name='反對數')
65
66 user = models.ForeignKey(to='UserInfo', verbose_name='作者',on_delete=models.CASCADE)
67 category = models.ForeignKey(to='Category', null=True, verbose_name='文章分類',on_delete=models.SET_NULL)
68 # 自己手動創建第三張表
69 tags = models.ManyToManyField(to='Tag', through='Article2Tag', through_fields=('article', 'tag'),
70 verbose_name='文章標簽')
71
72 def __str__(self):
73 return self.title
74
75
76 class Article2Tag(models.Model):
77 article = models.ForeignKey(to='Article', verbose_name='文章',on_delete=models.CASCADE)
78 tag = models.ForeignKey(to='Tag', verbose_name='標簽',on_delete=models.CASCADE)
79
80 class Meta:
81 # 聯合唯一
82 unique_together = [('article', 'tag'), ]
83
84 def __str__(self):
85 return self.article.title + '---' + self.tag.title
86
87
88 class ArticleUpDown(models.Model):
89 """
90 點贊表
91 """
92 user = models.ForeignKey('UserInfo', null=True,on_delete=models.CASCADE)
93 article = models.ForeignKey('Article', null=True,on_delete=models.CASCADE)
94 is_up = models.BooleanField(default=True)
95
96 class Meta:
97 unique_together = [
98 ('article', 'user'),
99 ]
100
101
102 class Comment(models.Model):
103 """
104 評論表:對文章的評論、對評論的評論
105 """
106 article = models.ForeignKey('Article', verbose_name='評論文章',on_delete=models.CASCADE)
107 user = models.ForeignKey('UserInfo', verbose_name='評論者',on_delete=models.CASCADE)
108 create_time = models.DateTimeField(auto_now_add=True, verbose_name='評論時間')
109 content = models.CharField(max_length=256, verbose_name='評論內容')
110 # 父評論 自關聯
111 parent_comment = models.ForeignKey(to='self', null=True,on_delete=models.CASCADE)
112
113 def __str__(self):
114 return self.content
表結構流程圖
說明:
USE_TZ = False 表示使用無時區的時間。TIME_ZONE = 'Asia/Shanghai' 表示使用本地時區。當True是,表示不管time_zone怎么設置,都不生效,所以我們一般設置為Flase。
LANGUAGE_CODE = 'zh-hans' 表示設置為中國區域,使用中文。
用戶信息表繼承的是Django內置的AbstractUser類,而不是User類。from django. contrib.auth.models import AbstractUser,這樣繼承有什么好處?雖然User本質也是繼承AbstractUser,但是為了我們擴展更多的自定義字段,就繼承AbstractUser。但是別忘了settings.py加AUTH_USER_MODEL = 'app01.UserInfo' 表示使用app01下的UserInfo模型類,生成的表也是app01_userinfo為名。
一個分類對應多篇文章,而分類刪除的時候,文章不能刪除,所以設置了
1 class Article(models.Model):
pass 2 category = models.ForeignKey(to='Category', null=True,verbose_name='文章分類',on_delete=models.SET_NULL) 3 # 文章也可以沒有分類,所以可以為null。
一個標簽對應多個文章,一個文章對應多個分類。是多對多關系,但是這里沒有使用Django自動創建第三張表,而是寫了個Article2Tag類,用來記錄article_id和tag_id的關系。
對于點贊、反對、評論三個功能。在Article類中增加三個字段記錄數目就行了。增加點贊表、反對表、評論表,與用戶直接建立關系,表示那個用戶對哪個文章進行了什么操作。
這里這里最難得屬評論表了,評論分兩種,一個是對文章的評論,一個是對評論的評論。
其實這里是利用了自關聯,
1 # 父評論 自關聯 2 parent_comment = models.ForeignKey(to='self', null=True,on_delete=models.CASCADE)
上面的表格的評論關系就一目了然了。
UserInfo模型類中還有一個頭像字段,用來保存用戶頭像的。這里要細說一下。
當用戶上傳頭像的時候,能拿到一個文件對象file_obj。但是我們怎么保存到我們服務器呢?
avatar = models.FileField(upload_to='avatars/', default='/avatars/default.png', verbose_name='頭像') 這里必須接收一個文件對象,但數據庫保存的只是一個文件相對路徑字符串,所以這肯定要配置,Django會幫我們把文件對象保存到我們upload=path的path路徑,如果沒有這個文件夾,將自動生成,前面我們都知道setting.py文件配置過
1 # 別名,用于url訪問 2 STATIC_URL = '/static/' 3 4 # 靜態文件存放路徑 5 STATICFILES_DIRS = [ 6 os.path.join(BASE_DIR, 'static') 7 ]
Django對靜態文件的區分有兩種
/static/ js、css、image、fonts等
/media/ 用戶上傳的文件
media和static配置類似:
1 # 絕對路徑 用來保存用戶上傳的文件 2 MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 3 # 讓用戶url可以訪問 但要配置urls.py 4 MEDIA_URL = '/media/'
5 # 會將文件下載到media文件夾中 以后文件都會保存到media文件夾下,耦合性非常棒,做到了統一
但這還不夠,static雖然在根目錄,但是用戶可以訪問,那些是無關緊要的,看了就看了,其他文件不能看,因為static是django已經幫我們配好路由,我們的media并沒有,用戶訪問不了,所以還要在urls.py
1 from django.views.static import serve
2 from . import settings
3 from django.urls import path, re_path
4
5 urlpatterns = [
6 # media配置
7 re_path(r'media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),
8 ]
別問為什么,就是這樣做,通過上面兩部,用戶上傳的頭像或文件會自動保存到/media/avatars/文件夾下,用戶url也可以訪問。
總結
- 上一篇: apper
- 下一篇: 让绿电接入电网,2040年前需新增或更换