热门文章功能,实现热门文章的增、删、改、查功能的实现
一、分析
1. 业务流程
1.热门文章展示
-
业务流程
- 从数据库中获取到数据然后传递给前端
- 前端填充到页面中
-
请求方式、地址、参数
- 请求方式:GET
- 请求地址:/admin/hot_article/
- 请求参数:无
2. 热门文章删除功能
-
业务流程
- 从前端传递一个带有热门文章id的delete请求
- 判断数据库中是否有该数据
- 逻辑删除该热门文章,并返回数据到前端
-
请求方式、地址、参数
-
请求方式:DELETE
-
请求地址:/admin/hot_article/<int:hot_article_id>/
-
请求参数:
参数名 类型 是否必传 备注 hot_article_id int 必传 路径参数
-
3. 热门文章修改功能
-
业务流程
- 判断priority文章优先级是否和以前的一样
- 判断priority是否在优先级规定的表内
- 接收前端传来的数据
- 判断该篇热门文章是否存在
- 对热门文章的优先级进行修改
- 返回数据到前端
-
请求方式、地址、参数
-
请求方式:PUT
-
请求地址:/admin/hot_article/<int:hot_article_id>/
-
请求参数:
参数名 类型 是否必传 备注 hot_article_id int 必传 路径参数 priority int 必传 请求体里
-
-
前端功能实
- 获取到优先级priority的值
- 判断priority文章优先级是否和以前的一样
- 判断priority是否在优先级规定的表内
- 发起ajax PUT请求
- 修改该条热门文章的信息
-
后端逻辑处理
- 接收前端传来的数据
- 判断该篇热门文章是否存在
- 判断priority文章优先级是否和以前的一样
- 判断priority是否在优先级规定的表内
- 对该篇热门文章的优先级进行修改
- 返回数据到前端
4. 热门文章添加功能
-
业务流程
- 发送文章类型、热门文章优先级到前端
- 构造点击文章类型时出现对应的所有该类型的文章
- 判断该篇文章是否存在
- 判断优先级是否满足要求
- 判断优先级是否在优先级列表中
- 创建新的热门文章
- 返回数据到前端
-
请求方式、地址、参数
-
请求方式:POST
-
请求地址:/admin/hot_add/
-
请求参数:
参数名 类型 是否必传 备注 article_id int 必传 请求体里 priority int 必传 请求体里
-
-
前端处理
- 获取到文章id和热门文章优先级
- 发送ajax POST请求
- 跳转到热门文章列表页
-
后端逻辑
- 构造文章类型、热门文章优先级到后端
- 获取到前端传来的数据
- 判断文章是否存在
- 判断文章优先级是否满足要求
- 判断热门文章优先级是否在优先级列表中
- 创建热门文章
- 返回数据到前端
二、热门文章展示、删除、修改功能实现
1. urls配置
from django.urls import path
from admin import views
app_name = "admin"
urlpatterns = [
path("hot_article/", views.HotArticleView.as_view(), name="hot_article"),
path("hot_article/<int:hot_article_id>/", views.HotArticleView.as_view(), name="hot_article_change"),
]
2. views视图逻辑处理
import json
from django.views import View
from django.shortcuts import render
from django.contrib.auth.mixins import PermissionRequiredMixin
from news import models
from utils.res_code.res_code import Code, error_map
from utils.res_code.json_function import to_json_data
# 热门文章删改查
class HotArticleView(PermissionRequiredMixin, View):
"""
hot article add/view/delete/edit function view
route:/admin/hot_article/ :view
route:/admin/hot_article/<int:article_id>/ :delete and edit
permissions:view_hotarticle/change_hotarticle/delete_hotarticle
"""
# 设置权限
permission_required = ("news.view_hotarticle", "news.change_hotarticle", "news.delete_hotarticle")
raise_exception = True
def get(self, request):
"""
hot article view
:param request:
:return:
"""
hot_articles = models.HotArticle.objects.only("id", "priority", "article__title",
"article__tag__name").filter(is_delete=False).order_by("priority")
return render(request, 'admin/news/hot_article.html', locals())
def put(self, request, hot_article_id):
"""
hot article priority change
:param request:
:return:
"""
# 获取亲阿杜那传来的数据
try:
json_data = request.body
if not json_data:
return to_json_data(errno=Code.PARAMERR, errmsg="参数错误")
dict_data = json.loads(json_data)
except Exception as e:
return to_json_data(errno=Code.UNKOWNERR, errmsg="未知错误")
# 获取到优先级
try:
priority = int(dict_data.get("priority"))
if priority not in [num for num, word in models.HotArticle.PRI_CHOICES]: # 判断输入的优先级是否在优先级表中
return to_json_data(errno=Code.UNKOWNERR, errmsg="设置的优先级不在优先级表中")
except Exception as e:
logger.info("热门文章优秀级异常:{}".format(e))
return to_json_data(errno=Code.PARAMERR, errmsg="热门文章优秀级设置错误")
# 判断文章是否存在
hot_article = models.HotArticle.objects.only("id").filter(id=hot_article_id).first()
if not hot_article:
return to_json_data(errno=Code.PARAMERR, errmsg="该热门文章不存在")
# 判断优先级是否有修改
if hot_article.priority == priority:
return to_json_data(errno=Code.PARAMERR, errmsg="优先级未修改")
# 保存
hot_article.priority = priority
hot_article.save(update_fields=["priority"])
return to_json_data(errmsg="优先级修改成功")
def delete(self, request, hot_article_id):
"""
hot article delete
:param request:
:return:
"""
hot_article = models.HotArticle.objects.only("id").filter(is_delete=False, id=hot_article_id).first()
if hot_article:
hot_article.is_delete = True
hot_article.save()
return to_json_data(errmsg="热门文章删除成功")
else:
return to_json_data(errno=Code.PARAMERR, errmsg="参数错误")
3. js前端逻辑实现
js里面使用到了两个js插件 fsweetalert.js 和 message.js
$(function () { //增删改查
let $editBtn = $(".btn-edit");
let $delBtn = $(".btn-del");
//热门文章删除
$delBtn.click(function () {
let _this = this;
let sHotArticleId = $(this).parents("tr").data("id");
let sHotArticleName = $(this).parents("tr").data("name");
fAlert.alertConfirm({ //弹窗
title:"确定删除" + sHotArticleName + "热门文章吗?",
type:"error",
confirmButtonText:"确认删除",
cancelButtonText:"取消",
confirmCallback:function confirmCallback() {
$.ajax({
url:"/admin/hot_article/" + sHotArticleId +"/",
type:"DELETE",
dataType:"json",
})
.done(function (res) {
if (res.errno === "200"){
message.showSuccess("成功删除 "+ sHotArticleName + " 热门文章!");
$(_this).parents("tr").remove()
}else{
swal.showInputError("删除失败:" + res.errmsg);
}
})
.fail(function () {
alert("服务器超时,请重试!")
})
}
}
)
});
//热门文章修改
$editBtn.click(function () {
let _this = this;
let sHotArticleId = $(this).parents("tr").data("id");
let sHotArticleName = $(this).parents("tr").data("name");
let sHotArticlePriority = $(this).parents("tr").data("priority");
fAlert.alertOneInput({
title:"编辑热门文章优先级",
text:"您正在编辑 " + sHotArticleName + " 优先级",
placeholder: "请输入优先级",
value:sHotArticlePriority,
confirmCallback:function callfirmCallback(inputval) {
if (inputval === sHotArticlePriority){
swal.showInputError("优先级没有改变");
return false
}else if($.inArray(inputval,["1", "2", "3"])){
swal.showInputError("优先级必须在1,2,3中选择");
}
let sDataParams={
"priority":inputval,
};
$.ajax({
url:"/admin/hot_article/" + sHotArticleId + "/",
type:"PUT",
data:JSON.stringify(sDataParams),
contentType: "application/json;charset=utf-8",
dataType:"json",
})
.done(function (res) {
if (res.errno==="200"){
$(_this).parents("tr").find("td:nth-child(3)").text(inputval); //更新标签
// $(_this).parent("tr").data("name",inputval); //更新data-name的值没有解决
swal.close();
message.showSuccess("优先级修改成功");
}else{
swal.showInputError("优先级修改失败:" + res.errmsg);
}
})
.fail(function () {
alert("服务器超时,请重试!")
})
}
})
});
// get cookie using jQuery
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// Setting the token on the AJAX request
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
});
4. html页面填充
{% extends 'admin/base/base.html' %}
{% load staticfiles %}
{% block title %}
热门文章管理页面
{% endblock %}
{% block content_header %}
热门文章管理
{% endblock %}
{% block content_header_brief %}
热门文章增删改查
{% endblock %}
{% block content %}
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12 col-xs-12 col-sm-12">
<div class="box box-primary">
<div class="box-header"><a href="
{% url 'admin:hot_add' %}">
<button class="btn btn-primary fa-pull-right" id="btn-add">添加热门文章</button></a>
</div>
<br>
<br>
<div class="box-body">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>文章名称</th>
<th>文章标签</th>
<th>优先级</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for hot_article in hot_articles %}
<tr data-id="{{ hot_article.id }}"
data-name="{{ hot_article.article.title }}" data-priority="{{ hot_article.priority }}">
<td><a href="{% url 'news:article_detail' hot_article.id %}"
>{{ hot_article.article.title }}</a></td>
<td>{{ hot_article.article.tag.name }}</td>
<td>{{ hot_article.priority }}</td>
<td>
<button class="btn btn-xs btn-warning btn-edit">
编辑
</button>
<button class="btn btn-xs btn-danger btn-del">
删除
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'js/admin/news/hot_article.js' %}"></script>
{% endblock %}
三、热门文章添加功能实现
1. urls配置
from django.urls import path
from admin import views
app_name = "admin"
urlpatterns = [
path("hot_add/", views.HotArticleAddView.as_view(), name="hot_add"),
path("tags/<int:tag_id>/article/", views.ArticleCategoryView.as_view(), name="article_add"),
]
2. views视图逻辑处理
import json
from collections import OrderedDict # 转化为字典
from django.views import View
from django.shortcuts import render
from django.http import JsonResponse
from django.contrib.auth.mixins import PermissionRequiredMixin
from news import models
from utils.res_code.res_code import Code, error_map
from utils.res_code.json_function import to_json_data
# 热门文章增:需要单独写一个类视图来处理
class HotArticleAddView(PermissionRequiredMixin, View):
"""
hot article add view
route:/admin/hot_article/add/
permissions:view_hotarticle/add_hotarticle
"""
permission_required = ("news.view_hotarticle", "news.add_hotarticle")
raise_exception = True
def get(self, request):
"""
传递给前端:tag、article、priority
:param request:
:return:
"""
tags = models.Tags.objects.only("id", "name").filter(is_delete=False).order_by("-id", "-update_time")
# priority_dict = {k: v for k, v in models.HotArticle.PRI_CHOICES} # 转化为字典
priority_dict = OrderedDict(models.HotArticle.PRI_CHOICES)
return render(request, 'admin/news/hot_add.html', context={"tags": tags, "priority_dict": priority_dict})
def post(self, request):
try:
json_data = request.body
if not json_data:
return to_json_data(erno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
dict_data = json.loads(json_data.decode("utf-8"))
except Exception as e:
logger.info("热门文章添加未知错误:{}".format(e))
return to_json_data(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])
try:
article_id = int(dict_data.get("article_id"))
except Exception as e:
logger.info("热门文章id错误:{}".format(e))
return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
if not models.Articles.objects.only("id").filter(is_delete=False, id=article_id).exists():
return to_json_data(errno=Code.PARAMERR, errmsg="文章不存在")
try:
priority = int(dict_data.get("priority"))
except Exception as e:
logger.info("热门文章优先级错误:{}".format(e))
return to_json_data(errno=Code.PARAMERR, errmsg="热门文章优先级设置错误")
priority_ls = [index for index, word in models.HotArticle.PRI_CHOICES]
if priority not in priority_ls:
return to_json_data(errno=Code.PARAMERR, errmsg="热门文章优先级设置错误")
# 创建热门文章
hot_article_tuple = models.HotArticle.objects.get_or_create(article_id=article_id)
hot_article, is_create = hot_article_tuple
hot_article.priority = priority
hot_article.save(update_fields=["priority"])
return to_json_data(errmsg="热门文章优先级添加成功")
# 文章分类:关联点击文章分类时显示对应的文章
class ArticleCategoryView(PermissionRequiredMixin, View):
"""
article category show
route:/admin/tags/<int:tag_id>/article/
permissions:view_tags/view_articles
"""
permission_required = ("news.view_tags","news.view_articles")
raise_exception = True
def get(self, request, tag_id):
articles = models.Articles.objects.values("id", "title").filter(is_delete=False, tag_id=tag_id)
if not articles:
return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
article_ls = [article for article in articles]
data = {
"articles": article_ls
}
return to_json_data(data=data)
3. js前端逻辑实现
$(function () {
let $tagSelect = $("#category-select"); // 获取选择分类标签元素
let $articleSelect = $("#article-select"); // 获取选择文章标签元素
let $saveBtn = $('#save-btn'); // 获取保存按钮元素
// 选择文章不同类别,获取相应的文章
$tagSelect.change(function () {
// 获取当前选中的下拉框的value
let sTagId = $(this).val();
if (sTagId === '0') {
$articleSelect.children('option').remove();
$articleSelect.append(`<option value="0">--请选择文章--</option>`);
return
}
// 根据文章分类id向后端发起get请求
$.ajax({
url: "/admin/tags/" + sTagId + "/article/", // url尾部需要添加/
type: "GET",
dataType: "json",
})
.done(function (res) {
if (res.errno === "200") {
$articleSelect.children('option').remove();
$articleSelect.append(`<option value="0">--请选择文章--</option>`);
res.data.articles.forEach(function (article) {
let content = `<option value="${article.id}">${article.title}</option>`;
$articleSelect.append(content)
});
} else {
// swal.showInputError(res.errmsg);
fAlert.alertErrorToast(res.errmsg);
}
})
.fail(function () {
message.showError('服务器超时,请重试!');
});
});
// 点击保存按钮执行的事件
$saveBtn.click(function () {
let priority = $("#priority").val();// 获取优先级
// 获取下拉框中选中的文章标签id 和 文章id
let sTagId = $tagSelect.val();
let sArticleId = $articleSelect.val();
// // 打印值
// console.log(`
// priority(优先级): ${priority}
// tagId(文章标签id): ${sTagId}
// newsId(文章id): ${sArticleId}
// `);
// 判断是否为 0, 表示在第一个 未选择
if (sTagId !== '0' && sArticleId !== '0' && priority !== '0') {
let sDataParams = {
"priority": priority,
"article_id": sArticleId
};
$.ajax({
url: "/admin/hot_add/", // 请求地址
type: "POST", // 请求方式
data: JSON.stringify(sDataParams),
contentType: "application/json; charset=utf-8",// 请求内容的数据类型(前端发给后端的格式)
dataType: "json",// 响应数据的格式(后端返回给前端的格式)
})
.done(function (res) {
if (res.errno === "200") {
message.showSuccess("热门文章创建成功");
setTimeout(function () {
window.location.href = '/admin/hot_article/';
}, 800)
} else {
// swal.showInputError(res.errmsg);
message.showError("热门文章创建失败" + res.errmsg);
}
})
.fail(function () {
message.showError('服务器超时,请重试!');
});
} else {
message.showError("文章分类、文章以及优先级都要选!");
}
});
// get cookie using jQuery
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
// Setting the token on the AJAX request
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
});
4. html页面填充
{% extends 'admin/base/base.html' %}
{% load staticfiles %}
{% block title %}
添加热门文章
{% endblock %}
{% block content_header %}
添加热门文章
{% endblock %}
{% block content_header_brief %}
创建热门文章
{% endblock %}
{% block content %}
<div class="content">
<div class="container-fluid">
<div class="box box-primary">
<div class="box-body">
<div class="form-horizontal">
<div class="form-group">
<label for="category-select" class="col-md-2 col-sm-2 control-label">选择文章</label>
<div class="col-md-2 col-sm-3">
<select name="category" id="category-select" class="form-control input-md">
<option value="0">--请选择文章分类--</option>
{% for tag in tags %}
<option value="{{ tag.id }}">{{ tag.name }}</option>
{% endfor %}
</select>
</div>
<br>
<div class="col-md-8 col-sm-7">
<label for="article-select" style="display: none;"></label>
<select name="article" class="form-control input-md" id="article-select">
<option value="0">--请选择文章--</option>
</select>
</div>
</div>
<div class="form-group">
<label for="priority" class="col-md-2 col-sm-2 control-label">选择优先级</label>
<div class="col-md-2 col-sm-3">
<select name="priority" id="priority" class="form-control input-md">
<option value="0">--请选择优先级--</option>
{% for key, value in priority_dict.items %}
<option value="{{ key }}">{{ value }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="box-footer">
<a href="javascript:void(0);" class="btn btn-primary fa-pull-left" id="save-btn">保存</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'js/admin/news/hot_add.js' %}"></script>
{% endblock %}
本文详细介绍了在Django项目中实现热门文章功能的全过程,包括热门文章的展示、删除、修改和添加功能的实现。通过分析业务流程,配置urls,编写views视图逻辑,前端js处理以及html页面填充,实现了对热门文章的CRUD操作。

480

被折叠的 条评论
为什么被折叠?



