上一张文章模块分析已经写到了需要实现哪些模块哪些功能,现在这一章就讲具体怎么实现这些功能。
根据文章模块分析中数据表的各字段和表之间的关系进行创建数据库表
news/models.py
from django.db import models
from utils.models import models as _models
class Tags(_models.BaseModel):
"""
news tags model
field:
name CharField
"""
name = models.CharField(max_length=64, verbose_name="文章标题", help_text="文章标题")
class Meta:
ordering = ["-update_time", "-id"] # 排序方式
db_table = "tb_tags"
verbose_name = "文章标签" # 在admins站点中的名字
verbose_name_plural = verbose_name # 显示复数的名字
def __str__(self):
return "文章标签:{}".format(self.name)
news/models.py
from django.db import models
from utils.models import models as _models
class Articles(_models.BaseModel):
"""
create news model
field:
title CharField
digest CharField
clicks CharField
content TextField
image_url URLField
tag ForeignKey
author ForeignKey
"""
# CASCADE :主表删除,从表全部删除
# PROTECT :
# SET_NULL :主表删除后,从表设置为NULL
# SET_DEFAULT :主表删除后,从表设置为默认值
# SET :主表删除后,从表调用一个可执行对象,然后将值返回给从表
# DO_NOTHING :主表删除后,从表什么都不做
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("Tags", on_delete=models.SET_NULL, null=True)
author = models.ForeignKey("users.Users", on_delete=models.SET_NULL, null=True)
class Meta:
ordering = ["-update_time", "-id"]
db_table = "tb_article"
verbose_name = "文章"
verbose_name_plural = verbose_name
def __str__(self):
return "文章标题:{}".format(self.title)
news/models.py
from django.db import models
from utils.models import models as _models
class HotArticle(_models.BaseModel):
"""
create hot news model
field:
priority IntegerField
news ForeignKey
"""
PRI_CHOICES = [
(1, "第一级"),
(2, "第二级"),
(3, "第三级"),
]
priority = models.IntegerField(default=3, choices=PRI_CHOICES, verbose_name="优先级", help_text="优先级")
article = models.OneToOneField("Articles", on_delete=models.CASCADE)
class Meta:
ordering = ["-update_time", "-id"]
db_table = "tb_hotarticle"
verbose_name = "热门文章"
verbose_name_plural = verbose_name
def __str__(self):
return "优先级:{}".format(self.priority)
news/models.py
from django.db import models
from utils.models import models as _models
class Banner(_models.BaseModel):
"""
create news banner model
field:
priority IntegerField
image_url URLField
news ForeignKey
"""
PRI_CHOICES = [
(1, "第一级"),
(2, "第二级"),
(3, "第三级"),
(4, "第四级"),
(5, "第五级"),
(6, "第六级"),
]
image_url = models.URLField(default="", verbose_name="轮播图url", help_text="轮播图url")
priority = models.IntegerField(default=6, choices=PRI_CHOICES, verbose_name="优先级", help_text="优先级")
article = models.OneToOneField("Articles", on_delete=models.CASCADE)
class Meta:
ordering = ["priority", "-update_time", "-id"]
db_table = "tb_banner"
verbose_name = "轮播图"
verbose_name_plural = verbose_name
def __str__(self):
return "优先级:{}".format(self.priority)
news/models.py
from django.db import models
from utils.models import models as _models
class Comments(_models.BaseModel):
"""
create news comments models
field:
content
author
news
parent
"""
content = models.TextField(verbose_name="评论内容", help_text="评论内容")
author = models.ForeignKey("users.Users", on_delete=models.SET_NULL, null=True)
article = models.ForeignKey("Articles", on_delete=models.CASCADE)
parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True) # 自我关联,多级评论,blank允许前端不传数据
class Meta:
ordering = ["-update_time", "-id"]
db_table = "tb_comments"
verbose_name = "评论内容"
verbose_name_plural = verbose_name
# 自定义字典转化
def to_dict_data(self):
comment_dict_data = {
"comment_id": self.id, # 评论id
"article_id": self.article.id, # 文章id
"content": self.content, # 评论内容
"update_time": self.update_time.strftime("%Y年%m月%d日 %H:%M"), # 更新日期
"author": self.author.username, # 评论人
"parent": self.parent.to_dict_data() if self.parent else None # 二级评论
}
return comment_dict_data
def __str__(self):
return "评论内容:{}".format(self.content)
每个表格公用的字段创建一个公用的来继承,少些代码
utils/models/models.py
from django.db import models
class BaseModel(models.Model):
"""
base model,public field
"""
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 # 用于其他模型继承,在数据迁移时不会创建表格
创建完后进行数据表的创建和迁移,使用Run manage.py Task…
makemigrations news # 生成表格
mkmigrate news # 迁移表格
添加测试数据
使用navicate直接添加sql数据文件,添加时要注意文件名要跟数据表对应
项目urls.py配置
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('news/', include("news.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
news/urls.py配置
from django.urls import path
from news import views
app_name = "news"
urlpatterns = [
path("index/", views.IndexView.as_view(), name="index"),
]
news/views.py
from django.views import View
from django.shortcuts import render
from news import models as _models
class IndexView(View):
"""
create index page
news_tag
"""
def get(self, request):
# 1. 文章标签数据获取
tag_list = _models.Tags.objects.only("name", "id").filter(is_delete=False) # 标签数据
# 2. 热门文章数据获取
hot_article_list = _models.HotArticle.objects.select_related("article").only("id", "article__title",
"article__image_url").filter(is_delete=False).order_by("priority", "-update_time", "-id")
return render(request, "news/index.html", locals())
templates/news/index.html
{# 热门文章 #}
{% block hot_news %}
<ul class="recommend-news">
{% for hot_article in hot_article_list %}
<li>
<a href="/news/{{ hot_article.id }}" target="_blank">
<div class="recommend-thumbnail">
<img src="{{ hot_article.article.image_url }}" alt="title">
div>
<p class="info">{{ hot_article.article.titile }}p>
a>
li>
{% endfor %}
ul>
{% endblock %}
{# 文章标签 #}
{% block news_tags %}
<nav class="news-nav">
<ul class="clearfix">
<li class="active"><a href="javascript:void(0)" data-id="0">最新资讯a>li>
{% for tag in tag_list %}
<li><a href="javascript:void(0)" data-id="{{ tag.id }}">{{ tag.name }}a>li>
{% endfor %}
ul>
nav>
{% endblock %}
项目urls.py配置
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('news/', include("news.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
news/urls.py配置
from django.urls import path
from news import views
app_name = "news"
urlpatterns = [
path("banner/", views.BannerView.as_view(), name="banner"),
]
news/views.py
from django.views import View
from django.shortcuts import render
from news import contains
from news import models as _models
from utils.res_code.json_function import to_json_data
class BannerView(View):
"""
news banner image
"""
def get(self, request):
# 1. 从数据库中获取数据
banner_queryset_list = _models.Banner.objects.select_related("article").only("image_url", "article__id",
"article__title").filter(
is_delete=False).order_by("priority", "-update_time", "-id")[0:contains.BANNER_IMAGE_NUMBER]
banner_list = []
# 2. 数据序列化
for banner_queryset in banner_queryset_list:
banner_list.append({
"image_url": banner_queryset.image_url,
"article_id": banner_queryset.article.id,
"article_title": banner_queryset.article.title,
})
data = {
"banner_list": banner_list
}
# 3. 返回数据到前端
return to_json_data(data=data)
static/js/news/banner.js
$(function () {
// 新闻轮播图功能
fn_load_banner();
let $banner = $('.banner');
let $picLi = $(".banner .pic li");
let $prev = $('.banner .prev');
let $next = $('.banner .next');
let $tabLi = $('.banner .tab li');
let index = 0;
// 小原点
$tabLi.click(function () {
index = $(this).index();
$(this).addClass('active').siblings('li').removeClass('active');
$picLi.eq(index).fadeIn(1500).siblings('li').fadeOut(1500);
});
// 点击切换上一张
$prev.click(function () {
index--;
if (index < 0) {
index = $tabLi.length - 1
}
$tabLi.eq(index).addClass('active').siblings('li').removeClass('active');
$picLi.eq(index).fadeIn(1500).siblings('li').fadeOut(1500);
}).mousedown(function () {
return false
});
//切换下一张
$next.click(function () {
auto();
}).mousedown(function () {
return false
});
// 图片向前滑动
function auto() {
index++;
index %= $tabLi.length;
$tabLi.eq(index).addClass('active').siblings('li').removeClass('active');
$picLi.eq(index).fadeIn(3000).siblings('li').fadeOut(3000);
}
// 定时器
let timer = setInterval(auto, 2000);
$banner.hover(function () {
clearInterval(timer)
}, function () {
auto();
});
function fn_load_banner() {
$.ajax({
url: "/news/banner/", // url尾部需要添加/// 请求地址
type: "GET",// 请求方式
async: false //关闭异步
})
.done(function (res) {
if (res.errno === "200") {
let content = ``;
let tab_content = ``; //按钮
res.data.banner_list.forEach(function (one_banner, index) {
if (index === 0) {
// 需要修改 href 接收后台传来的id号 响应详情页 one_banner.news_id
content = `
${one_banner.article_id} /">
${one_banner.image_url}" alt="${one_banner.article_title}">
`;
tab_content = ``;
} else {
content = `
${one_banner.article_id} /">${one_banner.image_url}" alt="${one_banner.article_title}">
`;
tab_content = ``;
}
$(".pic").append(content); // 内容
$(".tab").append(tab_content); // 标签
});
} else {
// 登录失败,打印错误信息
alert(res.errmsg);
}
})
.fail(function () {
alert('服务器超时,请重试!');
});
}
});