上一張文章模塊分析已經(jīng)寫到了需要實現(xiàn)哪些模塊哪些功能,現(xiàn)在這一章就講具體怎么實現(xiàn)這些功能。
一、文章數(shù)據(jù)庫模型設(shè)計
根據(jù)文章模塊分析中數(shù)據(jù)表的各字段和表之間的關(guān)系進(jìn)行創(chuàng)建數(shù)據(jù)庫表
1. 文章標(biāo)簽表
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="文章標(biāo)題", help_text="文章標(biāo)題")
class Meta:
ordering = ["-update_time", "-id"] # 排序方式
db_table = "tb_tags"
verbose_name = "文章標(biāo)簽" # 在admins站點中的名字
verbose_name_plural = verbose_name # 顯示復(fù)數(shù)的名字
def __str__(self):
return "文章標(biāo)簽:{}".format(self.name)
2. 文章表
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 :主表刪除后,從表設(shè)置為NULL
# SET_DEFAULT :主表刪除后,從表設(shè)置為默認(rèn)值
# SET :主表刪除后,從表調(diào)用一個可執(zhí)行對象,然后將值返回給從表
# DO_NOTHING :主表刪除后,從表什么都不做
title = models.CharField(max_length=150, verbose_name="文章標(biāo)題", help_text="文章標(biāo)題")
digest = models.CharField(max_length=200, verbose_name="文章摘要", help_text="文章摘要")
content = models.TextField(verbose_name="評論內(nèi)容", help_text="評論內(nèi)容")
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 "文章標(biāo)題:{}".format(self.title)
3. 熱門文章表
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="優(yōu)先級", help_text="優(yōu)先級")
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 "優(yōu)先級:{}".format(self.priority)
4. 文章輪播圖
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="優(yōu)先級", help_text="優(yōu)先級")
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 "優(yōu)先級:{}".format(self.priority)
5. 評論表
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="評論內(nèi)容", help_text="評論內(nèi)容")
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) # 自我關(guān)聯(lián),多級評論,blank允許前端不傳數(shù)據(jù)
class Meta:
ordering = ["-update_time", "-id"]
db_table = "tb_comments"
verbose_name = "評論內(nèi)容"
verbose_name_plural = verbose_name
# 自定義字典轉(zhuǎn)化
def to_dict_data(self):
comment_dict_data = {
"comment_id": self.id, # 評論id
"article_id": self.article.id, # 文章id
"content": self.content, # 評論內(nèi)容
"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 "評論內(nèi)容:{}".format(self.content)
6. 公用表
每個表格公用的字段創(chuàng)建一個公用的來繼承,少些代碼
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="創(chuàng)建時間")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新時間")
is_delete = models.BooleanField(default=False, verbose_name="邏輯刪除")
class Meta:
abstract = True # 用于其他模型繼承,在數(shù)據(jù)遷移時不會創(chuàng)建表格
-
創(chuàng)建完后進(jìn)行數(shù)據(jù)表的創(chuàng)建和遷移,使用Run manage.py Task…
makemigrations news # 生成表格
mkmigrate news # 遷移表格
-
添加測試數(shù)據(jù)
使用navicate直接添加sql數(shù)據(jù)文件,添加時要注意文件名要跟數(shù)據(jù)表對應(yīng)
二、文章標(biāo)簽功能和熱門文章功能
1. 路由urls.py設(shè)置
項目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"),
]
2. 后端view邏輯處理
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. 文章標(biāo)簽數(shù)據(jù)獲取
tag_list = _models.Tags.objects.only("name", "id").filter(is_delete=False) # 標(biāo)簽數(shù)據(jù)
# 2. 熱門文章數(shù)據(jù)獲取
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())
3. 前端html數(shù)據(jù)填充
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 %}
{# 文章標(biāo)簽 #}
{% 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 %}
三、文章輪播圖
1. 路由urls.py設(shè)置
項目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"),
]
2. 后端view邏輯處理
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. 從數(shù)據(jù)庫中獲取數(shù)據(jù)
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. 數(shù)據(jù)序列化
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. 返回數(shù)據(jù)到前端
return to_json_data(data=data)
3. 前端js實現(xiàn)
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 //關(guān)閉異步
})
.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號 響應(yīng)詳情頁 one_banner.news_id
content = `
<li style="display:block;"><a href="/news/${one_banner.article_id}/">
<img src="${one_banner.image_url}" alt="${one_banner.article_title}"></a></li>
`;
tab_content = `<li class="active"></li>`;
} else {
content = `
<li><a href="/news/${one_banner.article_id}/"><img src="${one_banner.image_url}" alt="${one_banner.article_title}"></a></li>
`;
tab_content = `<li></li>`;
}
$(".pic").append(content); // 內(nèi)容
$(".tab").append(tab_content); // 標(biāo)簽
});
} else {
// 登錄失敗,打印錯誤信息
alert(res.errmsg);
}
})
.fail(function () {
alert('服務(wù)器超時,請重試!');
});
}
});
|