上一張文章模塊分析已經(jīng)寫到了需要實現(xiàn)哪些模塊哪些功能,現(xiàn)在這一章就講具體怎么實現(xiàn)這些功能。
根據(jù)文章模塊分析中數(shù)據(jù)表的各字段和表之間的關系進行創(chuàng)建數(shù)據(jù)庫表
news/models.py
from django.db import modelsfrom utils.models import models as _modelsclass 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 # 顯示復數(shù)的名字 def __str__(self): return "文章標簽:{}".format(self.name)
news/models.py
from django.db import modelsfrom utils.models import models as _modelsclass 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 :主表刪除后,從表調(diào)用一個可執(zhí)行對象,然后將值返回給從表 # 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="評論內(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 "文章標題:{}".format(self.title)
news/models.py
from django.db import modelsfrom utils.models import models as _modelsclass 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)
news/models.py
from django.db import modelsfrom utils.models import models as _modelsclass 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)
news/models.py
from django.db import modelsfrom utils.models import models as _modelsclass 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) # 自我關聯(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)
每個表格公用的字段創(chuàng)建一個公用的來繼承,少些代碼
utils/models/models.py
from django.db import modelsclass 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)建完后進行數(shù)據(jù)表的創(chuàng)建和遷移,使用Run manage.py Task…
makemigrations news # 生成表格mkmigrate news # 遷移表格
添加測試數(shù)據(jù)
使用navicate直接添加sql數(shù)據(jù)文件,添加時要注意文件名要跟數(shù)據(jù)表對應
項目urls.py配置
from django.urls import path, includefrom django.conf import settingsfrom django.conf.urls.static import staticurlpatterns = [ path('news/', include("news.urls")),] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
news/urls.py配置
from django.urls import pathfrom news import viewsapp_name = "news"urlpatterns = [ path("index/", views.IndexView.as_view(), name="index"),]
news/views.py
from django.views import Viewfrom django.shortcuts import renderfrom news import models as _modelsclass IndexView(View): """ create index page news_tag """ def get(self, request): # 1. 文章標簽數(shù)據(jù)獲取 tag_list = _models.Tags.objects.only("name", "id").filter(is_delete=False) # 標簽數(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())
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, includefrom django.conf import settingsfrom django.conf.urls.static import staticurlpatterns = [ path('news/', include("news.urls")),] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
news/urls.py配置
from django.urls import pathfrom news import viewsapp_name = "news"urlpatterns = [ path("banner/", views.BannerView.as_view(), name="banner"),]
news/views.py
from django.views import Viewfrom django.shortcuts import renderfrom news import containsfrom news import models as _modelsfrom utils.res_code.json_function import to_json_dataclass 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)
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 = ` <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); // 標簽 }); } else { // 登錄失敗,打印錯誤信息 alert(res.errmsg); } }) .fail(function () { alert('服務器超時,請重試!'); }); }});