(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)

  上面的表格的评论关系就一目了然了。

扫描二维码关注公众号,回复: 3998385 查看本文章
  • 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对静态文件的区分有两种

  1. /static/         js、css、image、fonts等
  2. /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也可以访问。

 

猜你喜欢

转载自www.cnblogs.com/xjmlove/p/9935406.html