Blog项目——新闻模型
一、分析
我们现在的博客里面,包含了标签、轮播图、热门文章、文章和文章评论。此时所有数据都是一个死的,而我们想要让数据动态起来,我们就需要将这些东西在数据库中进行保存。因此我们可以对这五个进行数据库设计,下面是简单的分析:
- 文章分类表: name create_time update_time is_delete
- 文章表: title digest content clicks image_url author(一对多) tag(一对多关系)
- 文章评论表:content author(一对多关系) news()
- 热门文章表:news(一对一) pirority
- 轮播图表: image_url pirority news(一对一)
为了更加方便,我们可以看一下思维导图:
二、创建
我们先将tag数据库进行创建:
news/models.py
from django.db import models
# 文章分类
class Tag(models.Model):
name = models.CharField(max_length=64, verbose_name="文章分类名") # 一个中文就有三个字节
# 数据创建时间
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
# 更新时间
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
# 逻辑删除字段
iss_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
class Meta:
ordering = ['-update_time', '-id'] # 设置排序
db_table = "tb_tag" # 设置表名
verbose_name = "新闻分类标签" # 设置别名
def __str__(self):
return self.name
下面我们来看看轮播图的创建:
news/models.py
# 轮播图
class Banner(models.Model):
PRI_CHOICE = [ # 设置优先级列表
(1, "第一级"),
(2, "第二级"),
(3, "第三级"),
(4, "第四级"),
(5, "第五级"),
(6, "第六级"),
]
imgs_url = models.URLField(verbose_name="轮播图的url") # 设置图片的url
priority = models.IntegerField(choices=PRI_CHOICE, default=6, verbose_name="轮播图的优先级") # 设置轮播图优先级
# 数据创建时间
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
# 更新时间
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
# 逻辑删除字段
iss_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
class Meta:
db_table = "tb_banner"
verbose_name = "轮播图"
ordering = ["-update_time", "-id"]
def __str__(self):
return "轮播图{}".format(self.id)
上面我们发现,有许多的代码是重复的,我们可以把这些重复的代码抽取出来,把这个类变成一个抽象模型类。我们在创建新的模型的时候只需要继承这个类即可。
抽象模型类
utils/BaseModel.py
# -*- coding: utf-8 -*-
# @Auther:Summer
from django.db import models
class ModelBase(models.Model):
# 数据创建时间
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
# 更新时间
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
# 逻辑删除字段
is_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
class Meta:
abstract = True # 指明该类为抽象类,当进行数据迁移时,这个表不会被创建
当抽象模型类创建好之后,我们就可以在之前的代码中进行相应的修改了:
news/models.py
from django.db import models
from utils.BaseModel import ModelBase
# 文章分类
class Tag(ModelBase):
name = models.CharField(max_length=64, verbose_name="文章分类名") # 一个中文就有三个字节
class Meta:
ordering = ['-update_time', '-id'] # 设置排序
db_table = "tb_tag" # 设置表名
verbose_name = "新闻分类标签" # 设置别名
def __str__(self):
return self.name
# 轮播图
class Banner(ModelBase):
PRI_CHOICE = [ # 设置优先级列表
(1, "第一级"),
(2, "第二级"),
(3, "第三级"),
(4, "第四级"),
(5, "第五级"),
(6, "第六级"),
]
imgs_url = models.URLField(verbose_name="轮播图的url") # 设置图片的url
priority = models.IntegerField(choices=PRI_CHOICE, default=6, verbose_name="轮播图的优先级") # 设置轮播图优先级
# 有一个OneToOne的外键,需要关联new_id
class Meta:
db_table = "tb_banner"
verbose_name = "轮播图"
ordering = ["-update_time", "-id"]
def __str__(self):
return "轮播图{}".format(self.id)
有了上面的表之后,我们再根据图片就可以把所有的模型给创建出来:
from django.db import models
from utils.BaseModel import ModelBase
# 文章分类
class Tag(ModelBase):
name = models.CharField(max_length=64, verbose_name="文章分类名") # 一个中文就有三个字节
class Meta:
ordering = ['-update_time', '-id'] # 设置排序
db_table = "tb_tag" # 设置表名
verbose_name = "新闻分类标签" # 设置别名
def __str__(self):
return self.name
class News(ModelBase):
title = models.CharField(max_length=150, verbose_name="标题", help_text="标题")
digest = models.CharField(max_length=200, verbose_name="摘要", help_text="摘要")
content = models.TextField(verbose_name="内容", help_text="内容")
clicks = models.IntegerField(default=0, verbose_name="点击量", help_text="点击量")
image_url = models.URLField(default="", verbose_name="图片url", help_text="图片url")
tag = models.ForeignKey('Tag', on_delete=models.SET_NULL, null=True)
author = models.ForeignKey('user.Users', on_delete=models.SET_NULL, null=True) # 这里,user.Users前面一个为app的名字,后面的为模型名称
class Meta:
ordering = ['-update_time', '-id']
db_table = "tb_news" # 指明数据库表名
verbose_name = "新闻" # 在admin站点中显示的名称
def __str__(self):
return self.title
class Comments(ModelBase):
content = models.TextField(verbose_name="内容", help_text="内容")
author = models.ForeignKey('user.Users', on_delete=models.SET_NULL, null=True)
news = models.ForeignKey('News', on_delete=models.CASCADE)
class Meta:
ordering = ['-update_time', '-id']
db_table = "tb_comments" # 指明数据库表名
verbose_name = "评论" # 在admin站点中显示的名称
def __str__(self):
return '<评论{}>'.format(self.id)
class HotNews(ModelBase):
news = models.OneToOneField('News', on_delete=models.CASCADE)
priority = models.IntegerField(verbose_name="优先级", help_text="优先级")
class Meta:
ordering = ['-update_time', '-id']
db_table = "tb_hotnews" # 指明数据库表名
verbose_name = "热门新闻" # 在admin站点中显示的名称
def __str__(self):
return '<热门新闻{}>'.format(self.id)
# 轮播图
class Banner(ModelBase):
PRI_CHOICE = [ # 设置优先级列表
(1, "第一级"),
(2, "第二级"),
(3, "第三级"),
(4, "第四级"),
(5, "第五级"),
(6, "第六级"),
]
imgs_url = models.URLField(verbose_name="轮播图的url") # 设置图片的url
priority = models.IntegerField(choices=PRI_CHOICE, default=6, verbose_name="轮播图的优先级") # 设置轮播图优先级
news = models.OneToOneField('News', on_delete=models.CASCADE) # 主表删除,从表也自动删除
class Meta:
db_table = "tb_banner"
verbose_name = "轮播图"
ordering = ["-update_time", "-id"]
def __str__(self):
return "<轮播图{}>".format(self.id)
数据迁移
python manage,py makemigrations
python manage.py migrate
此时我们回去查看我们的数据库就发现数据表已经创建好了:
mysql> use Blog_Django;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+---------------------------+
| Tables_in_Blog_Django |
+---------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| django_content_type |
| django_migrations |
| django_session |
| tb_banner |
| tb_comments |
| tb_hotnews |
| tb_news |
| tb_tag |
| tb_users |
| tb_users_groups |
| tb_users_user_permissions |
+---------------------------+
14 rows in set (0.01 sec)
tag数据
为了测试,我们可以再根目录下床构建一个script的文件夹,然后创建一个tb_tag.sql文件,放入以下数据:
INSERT INTO `tb_tag` VALUES (1, now(), now(), 0, '运维工程师');
INSERT INTO `tb_tag` VALUES (2, now(), now(), 0, 'web开发工程师');
INSERT INTO `tb_tag` VALUES (3, now(), now(), 0, '测试工程师');
INSERT INTO `tb_tag` VALUES (4, now(), now(), 0, '爬虫工程师');
INSERT INTO `tb_tag` VALUES (5, now(), now(), 0, '数据分析工程师');
INSERT INTO `tb_tag` VALUES (6, now(), now(), 0, '算法工程师');
当数据配置好以后,我们就可以进入到目录下,使用数据导入命令:
cd script
mysql -uname -ppassword -D Blog_Django < tb_tag.sql
# mysql -uroot -ppassword -D 库名 < 数据
再当我们进行查询的时候就会发现数据已经创建了:
mysql> select * from tb_tag;
+----+----------------------------+----------------------------+------------+-----------------------+
| id | create_time | update_time | is_delete | name |
+----+----------------------------+----------------------------+------------+-----------------------+
| 1 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | 运维工程师 |
| 2 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | web开发工程师 |
| 3 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | 测试工程师 |
| 4 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | 爬虫工程师 |
| 5 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | 数据分析工程师 |
| 6 | 2021-01-28 12:24:35.000000 | 2021-01-28 12:24:35.000000 | 0 | 算法工程师 |
+----+----------------------------+----------------------------+------------+-----------------------+
6 rows in set (0.00 sec)
三、测试
我们可以将index页面的tag栏进行动态化展示:
news/views.py
def index(request):
# only 把需要的字段添加进去
tags = Tag.objects.only('name').filter(is_delete=False)
return render(request, "news/index.html", locals())
index.html
<!-- news-nav start-->
<nav class="news-nav">
<ul class="clearfix">
<li class="active"><a href="javascript:void(0)">最新资讯</a></li>
{% for tag in tags %}
<li><a href="javascript:void(0)" data-id="{{ tag.id }}">{{ tag.name }}</a></li>
{% endfor %}
</ul>
</nav>
<!-- news-nav end -->