一,前台

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. Redis 一些基本的概念和基础

    Redis 简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久 ...

  2. Java面向对象之类、接口、多态

    Java面向对象之类.接口.多态 类 class Person { // 实例属性 int age; String name; // 类属性 static int v = 1; // 构造器 publ ...

  3. 1-6SpringBoot之事务管理@Transactional

    以前学ssh ssm都有事务管理service层通过applicationContext.xml配置,所有service方法都加上事务操作: 用来保证一致性,即service方法里的多个dao操作,要 ...

  4. docker-compose 快速部署Prometheus,监控docker 容器, 宿主机,ceph -- cluster集群

    话不多说上菜: 现在环境是这样: ceph 4台: 192.168.100.21  ceph-node1 192.168.100.22  ceph-node2 192.168.100.23  ceph ...

  5. 设备树DTS 学习: uboot 传递 dtb 给 内核

    背景 得到 dtb 文件以后,我们需要想办法下载到 板子中,并给 Linux 内核使用. (高级版本的 uboot也有了 自己使用设备树支持,我们这里不讨论 uboot 使用的设备树) Linux 内 ...

  6. HiBench成长笔记——(2) CentOS部署安装HiBench

    安装Scala 使用spark-shell命令进入shell模式,查看spark版本和Scala版本: 下载Scala2.10.5 wget https://downloads.lightbend.c ...

  7. 在 Linux 上实现一段时间后自动登出非活动用户

    参考 编辑 ~/.bashrc 或 ~/.bash_profile 文件: $ vi ~/.bashrc 或, $ vi ~/.bash_profile 将下面行加入其中: TMOUT=100 这会让 ...

  8. MQ的调用

    mq调用(相关dll) using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collecti ...

  9. 注解方式实例化Java类

    context:component-scan标签: Sprng容器通过context:component-scan标签扫描其base-package标签属性值指定的包及其子包内的所有的类并实例化被@C ...

  10. C++ 检测物理内存以及磁盘空间

    BOOL CheckResource() { MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); GlobalMemoryStatusE ...