一,前台

1,添加文章 /views/admin/content_add.html

{% extends 'layout.html' %}
{% block main %}
<ol class="breadcrumb">
<li><a href="/admin">管理首页</a></li>
<li><span>添加分类</span></li>
</ol>
<h3>添加分类</h3>
<form method="POST">
<div class="form-group">
<label for="category_name">分类名称</label>
<input type="text" class="form-control" name="category_name" id="category_name" placeholder="Category Name">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
 
{% endblock %}
 
2,查看文章  /views/admin/content.html
 
{% extends 'layout.html' %}
{% block main %}
<ol class="breadcrumb">
<li><a href="/admin/content">内容首页</a></li>
<li><span>内容列表</span></li>
</ol>
<h3>内容列表</h3>
<table class="table table-bordered">
<tr>
<th>ID</th>
<th>标题</th>
<th>分类</th>
<th>简介</th>
<th>作者</th>
<th>添加时间</th>
<th>阅读量</th>
<th>操作</th>
</tr>
<!-- 循环输出数组 . id是对象,需要转换成字符串 -->
 
{% for content in contents %}
<tr>
<td> {{content._id.toString()}}</td>
<td> {{content.title}}</td>
 
<!-- 关联的具体使用 -->
<td> {{content.category.category_name}}</td>
 
<td> {{content.description}}</td>
<td> {{content.user.username}}</td>
<td> {{content.addTime|date('Y-m-d h:i:s')}}</td>
<td> {{content.views}}</td>
<td>
<!-- 【 错误的案例 : 忘记加路由 】 <a href="/content/edit?id={{content._id.toString()}}">修改</a> | -->
<a href="/admin/content/edit?id={{content._id.toString()}}">修改</a> |
<a href="/admin/content/delete?id={{content._id.toString()}}">删除</a>
</td>
{% endfor %}
</tr>
</table>
<div class="btn-group" role="group" aria-label="...">
<a href="/admin/content?page={{page-1}}" class="btn btn-default">上一页</a>
<a href="/admin/content?page={{page+1}}" class="btn btn-default">下一页</a>
<li>一共有 {{count}} 条数据</li>
<li>每页显示 {{limit}} 条数据</li>
<li>一共有 {{pages}} 页</li>
<li>当前是在 {{page}} 页</li>
</div>
{% endblock %}

3, 修改文章 /views/admin/content_edit.html

{% extends 'layout.html' %}
{% block main %}
<ol class="breadcrumb">
<li><a href="/admin">管理首页</a></li>
<li><span>文章内容编辑</span></li>
</ol>
<h3>文章内容编辑 -- {{content.title}}</h3>
<hr> <h4>调试</h4>
{% for category in categories %}
{{category._id.toString()}} , {{category.category_name}}
{% endfor %}
<hr>
<form method="POST">
<div class="form-group">
<label for="category">分类</label>
<select name="category" id="category" class="form-control">
<!--
var categories = []
 
【 读取category表 】
Content.find().populate('category').then((rs) => {
categories = rs
-->
{% for category in categories %}
{% if category._id==content.category._id%}
<option value="{{category._id.toString()}}" selected>{{category.category_name}}</option>
{% else %}
<option value="{{category._id.toString()}}">{{category.category_name}}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="title">标题</label>
<input type="text" class="form-control" value="{{content.title}}" name="title" id="title" placeholder="Title">
</div>
<!-- 自动截取简介 -->
<div class="form-group">
<label for="description">简介</label>
<textarea class="form-control" name="description" id="description" cols="30" rows="3"
placeholder="Description">{{content.description}}</textarea>
</div>
<div class="form-group">
<label for="content">内容</label>
<textarea class="form-control" name="content" id="content" placeholder="Content" cols="30" rows="6">{{content.content}}</textarea>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{% endblock %}
 
二,数据库
 
1,定义文章表 /schemas/contents.js
 
var mongoose = require('mongoose')
/**
* 创建表结构
*/
module.exports =new mongoose.Schema({
 
// 关联字段(object) ———— 与分类表的 _id , category_name 是一样的
category:{
// 类型
type:mongoose.Schema.Types.ObjectId, //【 要指定ObjectId的类型,请在声明中使用Schema.Types.ObjectId。 】
 
/** 引用 【 引用另一张表的原型 】 => 实现关联
*
* 1, Category 指的是 /models/Category模型
* 2, 配合路由数据库查询的 populate('category'),
* 3, populate('category') 中的category 表示 category字段
* 4, 具体使用, 模板文件中 : {{content.category.category_name}}
*/
ref:'Category' //
},
title:String,
description:{
type:String,
default:''
},
 
content:{
type:String,
default:''
},
 
/**
* 拓展 */
/**
* 关联字段 : 用户 ID
*
* 具体使用 : 在admin/content.add 路由的数据库保存字段中添加 user:req.userInfo._id.toString() 即可
*/
user:{
type:mongoose.Schema.Types.ObjectId,
ref:'User'
},
/**
* 添加时间
*
* 具体使用 :(自动生成)
*/
addTime:{
type:Date,
default:new Date()
},
/**
* 点击量(阅读量)
*
* 具体使用 :(自动生成)
*/
views:{
type:Number,
default:0
}
})
 
2,定义文章数据模型  /models/Content.js 
var mongoose = require('mongoose')
var contentSchema = require('../schemas/contents')
/**
* 创建模型
*/
module.exports= mongoose.model('Content',contentSchema)
 
 
 
三,后台路由和业务逻辑   /router/admin.js
 
/**内容首页 */
router.get('/content',(req,res)=>{
 
var page = Number(req.query.page || 1) // 如果没有传值,默认为1
var limit = 10
var pages = 1
Content.count().then((count)=>{
// 计算总页数,向上取整数,去最大值
pages = Math.ceil(count / limit)
 
// 页数取值不能超过总页数的值
page = Math.min(page,pages)
 
// 取值不能小于1
page = Math.max(page,1)
var skip = (page-1)*limit
// 排序 : sort({第一个参数表示根据什么排序 : 第二个参数只能是( 1 和 -1 : 1 表示升序 ,-1 表示降序 )})
// _id 值包含了时间戳
Content.find().sort({_id:-1}).limit(limit).skip(skip).populate(['category','user']).then((contents) => {
// console.log(contents)
res.render('admin/content',{
userInfo: req.userInfo,
contents:contents,
page:page,
pages:pages,
count:count,
limit:limit
})
 
})
})
 
 
})
/**文章添加 */
router.get('/content/add',(req,res)=>{
/**读取分类内容 */
Category.find().sort({_id:-1}).then(categories=>{
res.render('admin/content_add',{
userInfo:req.userInfo,
categories:categories
})
})
})
/** 文章添加 */
router.post('/content/add',(req,res)=>{
/** 一,验证 */
if(req.body.category==''){
res.render('admin/error',{
user:req.userInfo,
message:'分类不能为空'
})
return Promise.reject()
}
if(req.body.title==''){
res.render('admin/error',{
user:req.userInfo,
message:'标题不能为空'
})
return Promise.reject()
}
if(req.body.description==''){
res.render('admin/error',{
user:req.userInfo,
message:'简介不能为空'
})
return Promise.reject()
}
if(req.body.content==''){
res.render('admin/error',{
user:req.userInfo,
message:'内容不能为空'
})
return Promise.reject()
}
/** 二,保存 */
/**1,错误的示例 */
// Content.save().then(fs=>{
// if(fs){
// res.render('admin/success',{
// user:req.userInfo,
// message:'添加内容成功'
// })
// }
// })
new Content({
content:req.body.content,
title:req.body.title,
category:req.body.category,
description:req.body.description,
user:req.userInfo._id.toString()
}).save().then(fs=>{
if(fs){
res.render('admin/success',{
user:req.userInfo,
message:'添加内容成功',
url:'/admin/content'
})
}
})
})
/** 文章的修改 */
router.get('/content/edit',(req,res)=>{
var id = req.query.id || ''
// console.log('id=>'+id)
/**
* 从外部获取 categories (1)
*/
var categories = []
// 读取category表
 
/** ——————————————————————————————————————————————————————————————————————————【Bug】
* Content.find().sort({_id:-1}).populate('category').then((rs) => {
* —————————————————————————————————————————————————————————————————————————— 【Bug】
* */
Category.find().sort({_id:-1}).populate('category').then((rs) => {
 
/**
* 从外部获取 categories (2)
*/
categories = rs
 
return Content.findOne({
_id:id
}).populate('category')
}).then(content=>{
// console.log(('categories=>'+categories).yellow)
if(!content){
res.render('admin/error',{
user:req.userInfo,
message:'要修改的内容不存在',
url:'/admin/content'
})
}else{
res.render('admin/content_edit',{
user:req.userInfo,
content:content,
categories:categories
})
}
})
})
/**
* 保存修改的文章
*/
router.post('/content/edit',(req,res)=>{
var id = req.query.id || ''
console.log(('req.body.category=>'+req.body.description).yellow)
if(req.body.category==''){
res.render('admin/error',{
user:req.userInfo,
message:'分类不能为空'
})
return Promise.reject()
}
if(req.body.title==''){
res.render('admin/error',{
user:req.userInfo,
message:'标题不能为空'
})
return Promise.reject()
}
Content.update({
/**条件 */
_id:id
},{
/**更新的内容 */
content:req.body.content,
title:req.body.title,
category:req.body.category,
description:req.body.description,
}).then((fs)=>{
if(fs){
res.render('admin/success',{
user:req.userInfo,
message:'修改内容成功',
url:'/admin/content'
})
}
})
})
/**
* 文章删除
*/
router.get('/content/delete',(req,res)=>{
 
//获取要删除分类的id
var id = req.query.id || ''
//直接删除
Content.remove({
_id:id
}).then((rs)=>{
if(rs){
res.render('admin/success',{
user:req.userInfo,
message:'文章删除成功',
url:'/admin/content'
})
}
})
 
})

19 ~ express ~ 文章的增加 , 查看 ,修改 ,删除的更多相关文章

  1. ASP.NET MVC3 实例(六) 增加、修改和删除操作(二)

    http://www.jquery001.com/asp.net-mvc3-instance-add-update-delete2.html 上篇我们在 ASP.NET MVC3 中实现了添加操作,由 ...

  2. 在linux中,如何增加、修改、删除、暂停和冻结用户名

    在Linux中,如何增加.修改.删除.暂停和冻结用户名 在操作增加.修改和删除用户名前,先认识linux中两个最重要的文件,它们就是账号管理最重要文件“/etc/passwd”与“etc/shadow ...

  3. MongoDB增加用户、删除用户、修改用户读写权限及只读权限(注:转载于http://www.2cto.com/database/201203/125025.html)

    MongoDB  增加用户 删除用户  修改用户  读写权限 只读权限,   MongoDB用户权限分配的操作是针对某个库来说的.--这句话很重要.   1. 进入ljc 数据库:       use ...

  4. ASP.NET 操作Cookie详解 增加,修改,删除

    ASP.NET 操作Cookie详解 增加,修改,删除 Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它 ...

  5. Oracle 增加修改删除字段

    Oracle 增加修改删除字段 添加字段的语法:alter table tablename add (column datatype [default value][null/not null],…. ...

  6. MySql增加字段、删除字段、修改字段

    MySql增加字段.删除字段.修改字段名称.修改字段类型   1.增加一个字段 alter table user add COLUMN new1 VARCHAR(20) DEFAULT NULL; / ...

  7. Oracle-表的字段增加修改删除操作

    表结构修改 ALTER TABLE SCOTT.TEST RENAME TO TEST1--修改表名 ALTER TABLE SCOTT.TEST RENAME COLUMN NAME TO NAME ...

  8. EF里查看/修改实体的当前值、原始值和数据库值以及重写SaveChanges方法记录实体状态

    本文目录 查看实体当前.原始和数据库值:DbEntityEntry 查看实体的某个属性值:GetValue<TValue>方法 拷贝DbPropertyValues到实体:ToObject ...

  9. Laravel大型项目系列教程(四)显示文章列表和用户修改文章

    小编心语:不知不觉已经第四部分了,非常感谢很多人给小编提的意见,改了很多bug,希望以后能继续帮小编找找茬~小编也不希望误导大家~这一节,主要讲的 是如何显示文章列表和让用户修改文章,小编预告一下(一 ...

随机推荐

  1. priority_queue优先级队列总结

    http://www.cppblog.com/Darren/archive/2009/06/09/87224.html priority_queue用法 priority_queue 调用 STL里面 ...

  2. Dom4j 使用简介(全而好的文章)

    版权声明:本文由冰云完成,首发于CSDN,未经许可,不得使用于任何商业用途.文中代码部分引用自DOM4J文档.欢迎转载,但请保持文章及版权声明完整.如需联络请发邮件:icecloud(AT)sina. ...

  3. Bar Chart _Study

    ---恢复内容开始--- 以“3D BarChart”为例. 1.Select a theme.(选择一个主题模板) 2.Set up categories and groups.(设置类型和组) 3 ...

  4. Ubuntu操作系统编译安装zabbix报错汇总

    Ubuntu操作系统编译安装zabbix报错汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.报错提示:"configure: error: MySQL libra ...

  5. 牛客小白月赛3---G 旅游(树形dp)

    题目链接:https://www.nowcoder.com/acm/contest/87/G 分析: 1.对于点cur,dp[cur][0]表示在该点住宿:dp[cur][1]表示其某个子结点住宿,自 ...

  6. Prometheus Operator 架构【转】

    本节讨论 Prometheus Operator 的架构.因为 Prometheus Operator 是基于 Prometheus 的,我们需要先了解一下 Prometheus. Prometheu ...

  7. 洛谷P4427 [BJOI2018]求和

    \(\Large\textbf{Description: } \large{一颗n个节点的树,m次询问,每次查询点i到点j的路径上所有节点点深度的k次方的和并对998244353取模(1\leq n, ...

  8. Windows上设置Sass

    现在有很多信息在预处理器上浮动.大部分信息都面向Mac用户,所以在这篇文章中,我提供了一个非常简单的指南,帮助基于Windows的开发人员快速启动并运行Sass(我选择的预处理器). 本文是在此博客上 ...

  9. Ubuntu指令

    cd ~ 进入桌面 cd /进入计算机 mkdir 创建文件夹 mv移动文件  mv 源文件 目标文件 记得前面加/.

  10. 使用delphi TThread类创建线程备忘录

    备忘,不常用经常忘了细节 TMyThread = class(TThread) private { Private declarations } protected procedure Execute ...